package com.handset.serialportlib;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

@SuppressWarnings(value = "unused")
public class ByteUtils {
    private static final String HEX = "0123456789ABCDEF";

    private static byte charToByte(char c) {
        return (byte) HEX.indexOf(c);
    }

    public static byte[] hexStrToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return new byte[]{};
        }
        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) (ByteUtils.charToByte(hexChars[pos]) << 4 | ByteUtils.charToByte(hexChars[pos + 1]));
        }
        return d;
    }

    public static String bytesToHexStr(byte[] bArray) {
        StringBuilder sb = new StringBuilder(bArray.length);
        String sTemp;
        for (byte b : bArray) {
            sTemp = Integer.toHexString(0xFF & b);
            if (sTemp.length() < 2) {
                sb.append(0);
            }
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

    public static byte[] getByte4Id(String id) {
        byte year = (byte) Integer.parseInt(id.substring(0, 2));
        byte batch = (byte) Integer.parseInt(id.substring(2, 4));
        int num = Integer.parseInt(id.substring(4, 8));
        byte numHigh = (byte) (num >> 8 & 0xFF);
        byte numLow = (byte) (num & 0xFF);
        byte[] last = {year, batch, numHigh, numLow};
        return last;
    }

    public static long bytesToLong(byte[] b) {
        if (b.length != 4) {
            return -1;
        }
        return bytesToLong(b[0], b[1], b[2], b[3]);
    }

    private static long bytesToLong(byte b1, byte b2, byte b3, byte b4) {
        return (b1 & 0xFF) | ((b2 & 0xFF) << 8) | ((b3 & 0xFF) << 8 * 2) | ((b4 & 0xFF) << 8 * 3);
    }

    public static byte[] longToBytes(long l) {
        byte[] result = new byte[4];
        result[0] = (byte) (l & 0xFF);
        result[1] = (byte) (l >> 8 & 0xFF);
        result[2] = (byte) (l >> 16 & 0xFF);
        result[3] = (byte) (l >> 24 & 0xFF);
        return result;
    }

    public static int bytesToInt(byte b1, byte b2) {
        return (b1 & 0xFF) | ((b2 & 0xFF) << 8);
    }

    public static byte[] intToBytes(int value) {
        byte[] src = new byte[4];
        src[3] = (byte) ((value >> 24) & 0xFF);
        src[2] = (byte) ((value >> 16) & 0xFF);
        src[1] = (byte) ((value >> 8) & 0xFF);
        src[0] = (byte) (value & 0xFF);
        return src;
    }

    private static byte[] charsToBytes(char[] chars) {
        Charset cs = Charset.forName("UTF-8");
        CharBuffer cb = CharBuffer.allocate(chars.length);
        cb.put(chars);
        cb.flip();
        ByteBuffer bb = cs.encode(cb);

        return bb.array();
    }

    public static byte getByte(char c) {
        Charset cs = Charset.forName("UTF-8");
        CharBuffer cb = CharBuffer.allocate(1);
        cb.put(c);
        cb.flip();
        ByteBuffer bb = cs.encode(cb);

        byte[] tmp = bb.array();
        return tmp[0];
    }

    // byte转char
    public static char[] getChars(byte[] bytes) {
        Charset cs = Charset.forName("UTF-8");
        ByteBuffer bb = ByteBuffer.allocate(bytes.length);
        bb.put(bytes);
        bb.flip();
        CharBuffer cb = cs.decode(bb);

        return cb.array();
    }

    public static char toChar(byte bytes) {
        Charset cs = Charset.forName("UTF-8");
        ByteBuffer bb = ByteBuffer.allocate(1);
        bb.put(bytes);
        bb.flip();
        CharBuffer cb = cs.decode(bb);

        char[] tmp = cb.array();
        return tmp[0];
    }

    public static byte[] strToBytes(String s) {
        return strToBytes(s, 0);
    }

    public static String strToHexStr(String str) {
        StringBuilder sb = new StringBuilder();
        for (byte b : str.getBytes()) {
            sb.append(String.format("%x", b));
        }
        return sb.toString();
    }

    @SuppressWarnings(value = "SameParameterValue")
    private static byte[] strToBytes(String s, int length) {
        byte[] src = ByteUtils.charsToBytes((s == null || s.length() == 0) ? new char[0] : s.toCharArray());
        length = length < src.length ? src.length : length;

        byte[] bytes = new byte[length];
        System.arraycopy(src, 0, bytes, 0, src.length);
        return bytes;
    }

    public static byte[] copy(byte[] src, int srcStart, int length) {
        byte[] result = new byte[length];
        System.arraycopy(src, srcStart, result, 0, length);
        return result;
    }

    public static byte[] reverse(byte[] src) {
        for (int i = 0; i <= src.length / 2 - 1; i++) {
            byte temp1 = src[i];
            byte temp2 = src[src.length - i - 1];
            src[i] = temp2;
            src[src.length - i - 1] = temp1;
        }
        return src;
    }

    @SuppressWarnings(value = "SameParameterValue")
    private static String bytesToAscii(byte[] bytes, int offset, int dateLen) {
        if ((bytes == null) || (bytes.length == 0) || (offset < 0) || (dateLen <= 0)) {
            return null;
        }
        if ((offset >= bytes.length) || (bytes.length - offset < dateLen)) {
            return null;
        }

        for(byte b : bytes) {
            if(b < 32 || b > 126) {
                return "";
            }
        }

        String asciiStr = null;
        byte[] data = new byte[dateLen];
        System.arraycopy(bytes, offset, data, 0, dateLen);
        try {
            asciiStr = new String(data, StandardCharsets.ISO_8859_1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return asciiStr;
    }

    public static String bytesToAscii(byte[] bytes, int dateLen) {
        return bytesToAscii(bytes, 0, dateLen);
    }

    public static String bytesToAscii(byte[] bytes) {
        return bytesToAscii(bytes, 0, bytes.length);
    }

    /**
     * 字符串 转 ascii bytes
     * ISO-8859-1 码表兼容大部分码表，因此适合做中间码表
     */
    public static byte[] strToAsciiBytes(String s) {
        try {
            return s.getBytes(StandardCharsets.ISO_8859_1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new byte[0];
    }
}
