package com.xhpc.pp.utils;

import org.apache.commons.lang3.ArrayUtils;

import java.util.Objects;

public class HexUtils {

    /**
     * 字节数据转字符串专用集合
     */
    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    public static String toHexInt(long dec) {

        return toHex(toIntBytes(String.format("%08d", dec), 8));
    }

    public static String toHexIntYu(long dec) {

        return toHex(toIntBytes(String.format("%04d", dec), 4));
    }
    public static Integer reverseHexInt(String hex) {

        byte[] data = toBytes(reverseHex(hex));
        return toInteger(data, 0, data.length);
    }

    public static String reverseHex(String hex) {

        int len = hex.length();
        String revers = "";
        for (int i = len; i > 0; i = i - 2) {
            revers = revers.concat(hex.substring(i - 2, i));
        }
        return revers;
    }

    public static String toHex(byte[] data) {

        StringBuilder stringBuilder = new StringBuilder();
        for (byte datum : data) {
            // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
            stringBuilder.append(HEX_CHAR[(datum & 0xf0) >>> 4]);
            // 取出字节的低四位 作为索引得到相应的十六进制标识符
            stringBuilder.append(HEX_CHAR[(datum & 0x0f)]);
        }
        return stringBuilder.toString();

    }

    public static String toHex(byte[] data, int start, int end) {

        if (data == null || data.length < end)
            return "";
        return toHex(ArrayUtils.subarray(data, start, end));
    }

    public static String toString(byte[] data) {

        return new String(data);
    }

    public static String toString(byte[] data, int start, int end) {

        if (data == null || data.length < end)
            return "";
        return toString(ArrayUtils.subarray(data, start, end));
    }

    public static Integer toInteger(byte[] data, int start, int end) {

        if (data == null || data.length < end)
            return 0;
        String s = toHex(data, start, end);
        return Integer.decode("0x".concat(s));
    }

    public static byte[] toBytes(String hex) {

        if (hex == null) return null;
        hex = hex.trim();
        if (hex.length() == 0 || hex.length() % 2 != 0)
            return null;
        byte[] b = new byte[hex.length() / 2];
        for (int i = 0; i < hex.length(); i = i + 2) {
            b[i / 2] = Integer.decode("0x" + hex.substring(i, i + 2)).byteValue();
        }
        return b;
    }

    public static byte[] cp56toBytes(String hex) {

        if (hex == null) return null;
        hex = hex.trim();
        if (hex.length() != 14)
            return null;
        byte[] b = new byte[hex.length() / 2];
        for (int i = 0; i < hex.length(); i = i + 2) {
            if (i == 0) {
                b[i / 2] = Integer.decode("0x" + hex.substring(1, 2).concat(hex.substring(0, 1))).byteValue();
            } else {
                b[i / 2] = Integer.decode("0x" + hex.substring(i, i + 2)).byteValue();
            }
        }
        return b;
    }

    public static byte[] stringToBytes(String str, int len) {

        byte[] data = str.getBytes();
        if (data.length > len)
            return data;
        for (int i = data.length; i < len; i++)
            data = ArrayUtils.add(data, (byte) 0);
        return data;
    }

    public static String toIntString(String hex) {

        return toIntString(hex, 4);
    }

    public static String toIntString(String hex, int len) {

        if (hex == null || hex.length() == 0 || hex.length() % len != 0)
            return null;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hex.length(); i = i + len) {
            sb.append(String.format("%0" + len + "d", byte2int(Objects.requireNonNull(toBytes(hex.substring(i, i + len))))));
        }
        return sb.toString();
    }

    public static byte[] toIntBytes(String num, int len) {

        if (num == null || num.length() == 0 || num.length() % len != 0)
            return null;
        byte[] result = new byte[0];
        for (int i = 0; i < num.length(); i = i + len) {
            int n = Integer.parseInt(num.substring(i, i + len));

            result = ArrayUtils.addAll(result, toIntBytes(n, len / 2));
        }
        return result;
    }

    public static byte[] toIntBytes(int n, int len) {

        byte[] b = new byte[len];
        for (int i = 0; i < len; i++) {
            b[i] = (byte) (n >> i * 8 & 0xff);
        }
        return b;
    }

    public static int byte2int(byte[] b) {

        int res = 0;
        int bLen = b.length;
        if (bLen < 5) {// int 最大到4个字节
            for (int i = 0; i < bLen; i++) {
                res += (b[i] & 0xFF) << (8 * i);
            }
        }
        return res;
    }

    public static byte[] toLongBytes(long n) {

        byte[] b = new byte[4];
        for (int i = 0; i < 4; i++) {
            b[i] = (byte) ((n >> i * 8) & 0xff);
        }
        return b;
    }

    // 使用小端 字节index 0 对应 int 的最后一个字节
    public static long byte2Long(byte[] b) {

        long res = 0;
        int bLen = b.length;
        // int 最大到4个字节
        if (bLen < 9) {
            for (int i = 0; i < bLen; i++) {
                res += (b[i] & 0xFFL) << 8 * i;
            }
        }
        return res;
    }

    public static String toBits(String hex) {

        byte[] bytes = toBytes(hex);
        final StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            for (int i = 0; i < 8; i++) {
                result.append(b >> (8 - (i + 1)) & 0x0001);
            }
        }
        return result.toString();
    }

    public static final String toAscii(String hex) {

        if (hex == null) return null;
        byte[] bytes = toBytes(hex);
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(Character.valueOf((char) b));
        }
        return sb.toString();
    }

    public static void main(String[] args) {

//        System.out.println(Long.valueOf(10L).toString());
//        System.out.println(reverseHexInt("FF00"));
//        byte[] data1 = toBytes(reverseHex("10270000"));
//        System.out.println(toInteger(data1, 0, 4));
//        System.out.println(Integer.MAX_VALUE);
//        System.out.println(reverseHexInt("C350E900"));
//        System.out.println(reverseHexInt("B2900007"));
//        System.out.println(reverseHexInt("CB08"));
//        System.out.println(reverseHexInt("070090B2"));
        System.out.println(toHexIntYu(2l));
        System.out.println( HexUtils.toBytes(toHexIntYu(3l)));



//        System.out.println(toHexInt(3800));
//        System.out.println(toHexInt(100000));
//        System.out.println(toBits("1000"));
//        System.out.println(toHex(new byte[]{104, 13, 19, 123, 0, 3, 105, -123, 71, -123, -106, 50, 84, 1, 0, 72, 106, 104,
//        -94, 19, 124, 0, 59, 105, -123, 71, -123, -106, 50, 84, 1, 33, 9, 24, 9, 67, 57, 0, 2, 105, -123, 71, -123, -106,
//        50, 84, 1, -88, 97, 43, 9, 50, 9, 21, 48, 117, 50, 9, 50, 9, 21, -64, 87, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
//        -40, 83, 1, 0}));

    }

    public static String toBinaryString(String hex) {

        String hex_char, bin_char, binary;
        binary = "";
        int len = hex.length() / 2;
        for (int i = 0; i < len; i++) {
            hex_char = hex.substring(2 * i, 2 * i + 2);
            int conv_int = Integer.parseInt(hex_char, 16);
            bin_char = Integer.toBinaryString(conv_int);
            bin_char = zero_pad_bin_char(bin_char);
            if (i == 0) binary = bin_char;
            else binary = binary + bin_char;
            //out.printf("%s %s\n", hex_char,bin_char);
        }
        return binary;
    }

    public static String zero_pad_bin_char(String bin_char) {

        int len = bin_char.length();
        if (len == 8) return bin_char;
        String zero_pad = "0";
        for (int i = 1; i < 8 - len; i++) zero_pad = zero_pad + "0";
        return zero_pad + bin_char;
    }

}
