package com.sy.coinage.util;


import org.slf4j.Logger;

import javax.servlet.http.HttpServletRequest;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * Created by liuhong on 2020/5/9.
 */
public class Common {

    /**
     * 计算校验码 异或
     * 7e8001da7e
     * byte param = srcArr[1];
     *
     * @param srcArr
     * @return
     */
    public static boolean xorValidationCodeWhole(byte[] srcArr, byte compare) {
        byte startByte = srcArr[0];
        for (int index = 1; index < srcArr.length - 1; index++) {
            startByte = (byte) (startByte ^ srcArr[index]);
        }
        return startByte == compare;
    }

    /**
     * 计算校验码 异或
     * 8001000502
     * byte param = srcArr[0];
     *
     * @param srcArr
     * @return
     */
    public static byte xorValidationCodePart(byte[] srcArr, int startPos, byte param) {
        for (int index = startPos; index < srcArr.length; index++) {
            param = (byte) (param ^ srcArr[index]);
        }
        return param;
    }

    /**
     * 将 Big-Endian 的字节数组转为 int 类型的数据<br />
     * Big-Endian 表示高位字节在低位索引中
     *
     * @param bys   字节数组
     * @param start 需要转换的开始索引位数
     * @param len   需要转换的字节数量
     * @return 指定开始位置和长度以 BE 方式表示的 int 数值
     */
    public static int bytes2IntBE(byte[] bys, int start, int len) {
        return bytes2Int(bys, start, len, true);
    }

    public static int bytes2IntBE(byte[] bys) {
        return bytes2Int(bys, 0, bys.length, true);
    }

    /**
     * 将字节数组转为 Java 中的 int 数值
     *
     * @param bys         字节数组
     * @param start       需要转换的起始索引点
     * @param len         需要转换的字节长度
     * @param isBigEndian 是否是 BE（true -- BE 序，false -- LE 序）
     * @return
     */
    private static int bytes2Int(byte[] bys, int start, int len,
                                 boolean isBigEndian) {
        int n = 0;
        for (int i = start, k = start + len % (Integer.SIZE / Byte.SIZE + 1); i < k; i++) {
            n |= (bys[i] & 0xff) << ((isBigEndian ? (k - i - 1) : i) * Byte.SIZE);
        }
        return n;
    }

    /**
     * 整形数转为四个长度的字节数组
     *
     * @param number
     * @return
     */
    public static byte[] intToByteArray(int number) {
        byte[] result = new byte[4];
        result[0] = (byte) ((number >> 24) & 0xFF);
        result[1] = (byte) ((number >> 16) & 0xFF);
        result[2] = (byte) ((number >> 8) & 0xFF);
        result[3] = (byte) (number & 0xFF);
        return result;
    }




    /**
     * 整形数转为两个长度的字节数组
     *
     * @param number
     * @return
     */
    public static byte[] intToBytesBE(int number) {
        int temp = number;
        byte[] b = new byte[2];
        b[0] = new Integer((temp >> 8) & 0xff).byteValue();
        b[1] = new Integer(temp & 0xff).byteValue();
        return b;
    }

    /**
     * long类型转成byte数组
     *
     * @param number
     * @return
     */
    public static byte[] longToBytes(long number) {
        long temp = number;
        byte[] b = new byte[4];
        for (int i = b.length - 1; i >= 0; i--) {
            b[i] = new Long(temp & 0xff).byteValue();//
//            将最低位保存在最低位
            temp = temp >> 8;// 向右移8位
        }
        return b;
    }


    /**
     * byte数组转成long
     *
     * @param b
     * @return
     */
    public static long bytesToLong(byte[] b) {
        long hBit = (b[0] & 0xff);
        return (b[3] & 0xff) | ((b[2] & 0xff) << 8) | ((b[1] & 0xff) << 16) | (hBit << 24);
    }

    /**
     * byte 数组转为二进制字符串 100101格式
     *
     * @param bytes
     * @param radix
     * @return
     */
    public static String binary(byte[] bytes, int radix) {
        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数
    }


    /**
     * byte数组转为hexStr，方便记录日志
     *
     * @param src
     * @return
     */
    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }


    /**
     * hexStr转为byte数组，方便测试
     *
     * @param hexString
     * @return
     */
    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

        }
        return d;
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }


    /**
     * float类型转换成16进制
     * @param changeData
     * @return
     */
    public static String floatToHex(float changeData){
        return Integer.toHexString(Float.floatToIntBits(changeData));
    }

    /**
     *16进制转换为float类型
     * @param changeData
     * @return
     */
    public static float hexToFloat(String changeData){
        return Float.intBitsToFloat(Integer.parseInt(changeData,16));
    }

    /**
     *16进制转换为float类型 如果包含负数就要此方法
     * @param changeData
     * @return
     */
    public static float hexToFloat2(String changeData){
        return Float.intBitsToFloat(new BigInteger(changeData, 16).intValue());
    }


    public static byte[] floatToByte(float data)
    {
        int intBits = Float.floatToIntBits(data);
        return intToByteArray(intBits);
    }

    /**
     *  4byte  to int
     *  将4个字节转换为int
     * @param bytes
     * @return
     */
    public static int byteToInt(byte[] bytes)
    {
        return (0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)) | (0xff0000 & (bytes[2] << 16)) | (0xff000000 & (bytes[3] << 24));
    }

    /**
     * 将 字节数组 转换为 bytes
     * @param bytes
     * @return
     */
    public static float byteToFloat(byte[] bytes)
    {
        return Float.intBitsToFloat(byteToInt(bytes));
    }




    //获取时间戳 6 byte
    public static byte[] getTimestamp(){

        Calendar cal = Calendar.getInstance();
        // int year = cal.get(Calendar.YEAR);//获取年份
        //
        String year = new SimpleDateFormat("yy", Locale.CHINESE).format(cal.getTime());

        int month=cal.get(Calendar.MONTH);//获取月份
        int day=cal.get(Calendar.DATE);//获取日
        int hour=cal.get(Calendar.HOUR);//小时
        int minute=cal.get(Calendar.MINUTE);//分
        int second=cal.get(Calendar.SECOND);//秒

        byte[] time = new byte[6];
        time[0]=(byte)Integer.parseInt(year);
        time[1]=(byte)month;
        time[2]=(byte)day;
        time[3]=(byte)hour;
        time[4]=(byte)minute;
        time[5]=(byte)second;
        return time;

    }



    /**
     *  将6byte转换为时间戳字符串
     */
    public static  String obtainTimeSign(byte[] bytes){
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Calendar cal = Calendar.getInstance();
        int year = bytes[0];//四位中的后两位  2019 年的19
        int month = bytes[1];
        int day = bytes[2];
        int hour = bytes[3];
        int minitue = bytes[4];
        int second = bytes[5];

        year =Integer.parseInt("20"+year);

        cal.set(year,month-1,day,hour,minitue,second);

        return df.format(cal.getTime());

    }


    /**
     * byte数组转int类型的对象
     * @param bytes
     * @return
     */
    public static  int byte2Int(Byte[]bytes) {
        return (bytes[0]&0xff)<<24
                | (bytes[1]&0xff)<<16
                | (bytes[2]&0xff)<<8
                | (bytes[3]&0xff);
    }


    //按照日期获取DataTranslate对象byte[]
    public static byte[]  dateToDateTranslateByte(Date date){

        Calendar cal = Calendar.getInstance();
        if(date!=null) {
            cal.setTime(date);
        }
        //
        String year = new SimpleDateFormat("yyyy", Locale.CHINESE).format(cal.getTime());

        int month=cal.get(Calendar.MONTH)+1;//获取月份
        int day=cal.get(Calendar.DATE);//获取日
        int weekDay =cal.get(Calendar.DAY_OF_WEEK);//星期几
        int hour=cal.get(Calendar.HOUR_OF_DAY);//小时 24小时制
        int minute=cal.get(Calendar.MINUTE);//分
        int second=cal.get(Calendar.SECOND);//秒
        int nanoSecond =0;//毫秒

        System.out.println(" nanoSecond  is  :"+ nanoSecond+"  hour:"+hour);

        byte[] time = new byte[12];
        System.arraycopy(Common.intToBytesBE(Integer.parseInt(year)),0,time,0,2);
        time[2] = (byte)month;
        time[3] = (byte)day;
        time[4] = (byte)weekDay;
        time[5] = (byte)hour;
        time[6] = (byte)minute;
        time[7] = (byte)second;

        System.arraycopy(Common.intToByteArray(nanoSecond),0,time,8,4);


        return time;
    }




    public static void main(String args[]){

        String s="49f91901";
        Float value = Float.intBitsToFloat(Integer.valueOf(s.trim(), 16));
        System.out.println(value);

        Float f=02040608.154f;
        System.out.println(Integer.toHexString(Float.floatToIntBits(f)));


        //
        byte hour = 1;
        System.out.println(hour);



        String hexString="300833B2DDD9014000000000";

        //30 08 33 B2 DD D9 01 40 00 00 00 00
        byte[]  tt= hexStringToBytes(hexString);

        String str = new String(tt);

        System.out.println(str);

        String rfid = "232-oK6UzAPn";

        String rfidHex = bytesToHexString(rfid.getBytes());

        System.out.println("rfidHex=>" + rfidHex);

        byte[] rfidBytes = hexStringToBytes(rfidHex);
        String rfidStr = new String(rfidBytes);
        System.out.println("rfid src:"+rfid +"  rfidHex:"+rfidHex+"   rfidStr:"+rfidStr);


    }


    /**
     * 将data字节型数据转换为无符号字节0~255 (0xFF 即BYTE)。
     * @param data
     * @return
     */
    public static int getUnsignedByte(byte data){ //
        return data & 0x0FF ;
    }

    /**
     * 将data字节型数组转换为无符号字节0~255 (0xFF 即BYTE)的int类型
     * @param data
     * @return
     */
    public static int unsignedByteToInt(byte... data){
        if (data.length > 0 ){
            int sum = 0;
            for (int i = 0; i < data.length; i++){
                sum += getUnsignedByte(data[i]) * Math.pow(256,data.length - i);
            }
            return sum;
        }else{
            return 0;
        }
    }

    /**
     * RFID 校验和
     * @param uBuff
     * @return
     */
    public static byte checkSum(byte[] uBuff)
    {
        byte uSum=0;
        for(int i = 0; i < uBuff.length; i++) {
            uSum += uBuff[i];
        }
        return (byte)(~uSum + 1 & 0xFF);
    }

    /**
     *   rfid校验和算法
     * @param btAryBuffer
     * @param nStartPos
     * @param nLen
     * @return  校验位
     */
    public static byte checkSum(byte[] btAryBuffer, int nStartPos, int nLen) {
        byte btSum = 0;

        for(int nloop = nStartPos; nloop < nStartPos + nLen; ++nloop) {
            btSum += btAryBuffer[nloop];
        }



        return (byte)(~btSum + 1 & 255);
    }

    /**
     *  红外板卡 ：位校验和算法
     * @param btAryBuffer
     * @param nStartPos
     * @param nLen
     * @return
     */
    public static byte checkSumOfInfrared(byte[] btAryBuffer, int nStartPos, int nLen) {
        byte btSum = 0;

        for(int nloop = nStartPos; nloop < nStartPos + nLen; ++nloop) {
            btSum += btAryBuffer[nloop];
        }

        return btSum;
    }

    /**
     * 记录错误日志
     * @param log
     * @param ex
     * @param request
     */
    public static void WebErrorLog(Logger log, Throwable ex, HttpServletRequest request) {
        StringBuffer url=request.getRequestURL();
        String queryString=request.getQueryString();
        if(queryString!=null && !"".equals(queryString)) {
            url.append("?").append(queryString);
        }

        log.error("---ControllerException Handler---invokes url {} ERROR: {}",
                url.toString(), ex.getMessage(), ex);
    }

}
