package com.huashe.park.common;

import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.huashe.park.common.animations.FixedLength;

/**
 * @author : chencheng
 * @date : 2020-05-01
 * @desc : 字节数组与基本数据类型的转换 byte、short、int、float、long、double、16进制字符串
 * @version: 1.0
 */
public class ByteArrayUtil {

    /**
     * 字节数组转 short，小端
     */
    public static short byteArray2Short_Little_Endian(byte[] array) {
        // 数组长度有误
        if (array.length > 2) {
            return 0;
        }

        short value = 0;
        for (int i = 0; i < array.length; i++) {
            // & 0xff，除去符号位干扰
            value |= ((array[i] & 0xff) << (i * 8));
        }
        return value;
    }

    /**
     * 字节数组转 short，大端
     */
    public static short byteArray2Short_Big_Endian(byte[] array) {
        // 数组长度有误
        if (array.length > 2) {
            return 0;
        }
        short value = 0;
        for (int i = 0; i < array.length; i++) {
            value |= ((array[i] & 0xff) << ((array.length - i - 1) * 8));
        }
        return value;
    }

    /**
     * 字节数组转 int，小端
     */

    public static int byteArray2Int_Little_Endian(byte[] array) {
        // 数组长度有误
        if (array.length > 4) {
            return 0;

        }

        int value = 0;

        for (int i = 0; i < array.length; i++) {

            value |= ((array[i] & 0xff) << (i * 8));

        }

        return value;

    }

    /**
     * 字节数组转 int，大端
     */

    public static int byteArray2Int_Big_Endian(byte[] array) {

        // 数组长度有误

        if (array.length > 4) {

            return 0;

        }

        int value = 0;

        for (int i = 0; i < array.length; i++) {

            value |= ((array[i] & 0xff) << ((array.length - i - 1) * 8));

        }

        return value;

    }

    /**
     * 字节数组转 float，小端
     */

    public static float byteArray2Float_Little_Endian(byte[] array) {

        // 数组长度有误

        if (array.length != 4) {

            return 0;

        }

        return Float.intBitsToFloat(byteArray2Int_Little_Endian(array));

    }

    /**
     * 字节数组转 float，大端
     */

    public static float byteArray2Float_Big_Endian(byte[] array) {

        // 数组长度有误

        if (array.length > 4) {

            return 0;

        }

        return Float.intBitsToFloat(byteArray2Int_Big_Endian(array));

    }

    /**
     * 字节数组转 long，小端
     */

    public static long byteArray2Long_Little_Endian(byte[] array) {

        // 数组长度有误

        if (array.length != 8) {

            return 0;

        }

        long value = 0;

        for (int i = 0; i < array.length; i++) {

            // 需要转long再位移，否则int丢失精度

            value |= ((long) (array[i] & 0xff) << (i * 8));

        }

        return value;

    }

    /**
     * 字节数组转 long，大端
     */

    public static long byteArray2Long_Big_Endian(byte[] array) {

        // 数组长度有误

        if (array.length != 8) {

            return 0;

        }

        long value = 0;

        for (int i = 0; i < array.length; i++) {

            value |= ((long) (array[i] & 0xff) << ((array.length - i - 1) * 8));

        }

        return value;

    }

    /**
     * 字节数组转 double，小端
     */

    public static double byteArray2Double_Little_Endian(byte[] array) {

        // 数组长度有误

        if (array.length != 8) {

            return 0;

        }

        return Double.longBitsToDouble(byteArray2Long_Little_Endian(array));

    }

    /**
     * 字节数组转 double，大端
     */

    public static double byteArray2Double_Big_Endian(byte[] array) {

        // 数组长度有误

        if (array.length != 8) {

            return 0;

        }

        return Double.longBitsToDouble(byteArray2Long_Big_Endian(array));

    }

    /**
     * 字节数组转 HexString
     */

    public static String byteArray2HexString(byte[] array) {

        StringBuilder builder = new StringBuilder();

        for (byte b : array) {

            String s = Integer.toHexString(b & 0xff);

            if (s.length() < 2) {

                builder.append("0");

            }

            builder.append(s);

        }

        return builder.toString().toUpperCase();

    }

    // ---------------------------------华丽的分割线-------------------------------------

    /**
     * short 转字节数组，小端
     */

    public static byte[] short2ByteArray_Little_Endian(short s) {

        byte[] array = new byte[2];
        for (int i = 0; i < array.length; i++) {
            array[i] = (byte) (s >> (i * 8));
        }

        return array;

    }

    /**
     * short 转字节数组，大端
     */

    public static byte[] short2ByteArray_Big_Endian(short s) {

        byte[] array = new byte[2];

        for (int i = 0; i < array.length; i++) {

            array[array.length - 1 - i] = (byte) (s >> (i * 8));

        }

        return array;

    }

    /**
     * int 转字节数组，小端
     */

    public static byte[] int2ByteArray_Little_Endian(int s) {

        byte[] array = new byte[4];

        for (int i = 0; i < array.length; i++) {

            array[i] = (byte) (s >> (i * 8));

        }

        return array;

    }

    /**
     * int 转字节数组，大端
     */

    public static byte[] int2ByteArray_Big_Endian(int s) {

        byte[] array = new byte[4];

        for (int i = 0; i < array.length; i++) {

            array[array.length - 1 - i] = (byte) (s >> (i * 8));

        }

        return array;

    }

    /**
     * float 转字节数组，小端
     */

    public static byte[] float2ByteArray_Little_Endian(float f) {

        return int2ByteArray_Little_Endian(Float.floatToIntBits(f));

    }

    /**
     * float 转字节数组，大端
     */

    public static byte[] float2ByteArray_Big_Endian(float f) {

        return int2ByteArray_Big_Endian(Float.floatToIntBits(f));

    }

    /**
     * long 转字节数组，小端
     */

    public static byte[] long2ByteArray_Little_Endian(long l) {

        byte[] array = new byte[8];

        for (int i = 0; i < array.length; i++) {

            array[i] = (byte) (l >> (i * 8));

        }

        return array;

    }

    /**
     * long 转字节数组，大端
     */

    public static byte[] long2ByteArray_Big_Endian(long l) {

        byte[] array = new byte[8];

        for (int i = 0; i < array.length; i++) {

            array[array.length - 1 - i] = (byte) (l >> (i * 8));

        }

        return array;

    }

    /**
     * double 转字节数组，小端
     */

    public static byte[] double2ByteArray_Little_Endian(double d) {

        return long2ByteArray_Little_Endian(Double.doubleToLongBits(d));

    }

    /**
     * double 转字节数组，大端
     */

    public static byte[] double2ByteArray_Big_Endian(double d) {

        return long2ByteArray_Big_Endian(Double.doubleToLongBits(d));

    }

    /**
     * HexString 转字节数组
     */

    public static byte[] hexString2ByteArray(String hexString) {
        // 两个十六进制字符一个 byte，单数则有误
        if (hexString.length() % 2 != 0) {

            return null;

        }

        byte[] array = new byte[hexString.length() / 2];

        int value = 0;

        for (int i = 0; i < hexString.length(); i++) {

            char s = hexString.charAt(i);

            // 前半个字节

            if (i % 2 == 0) {

                value = Integer.parseInt(String.valueOf(s), 16) * 16;

            }
            else {

                // 后半个字节

                value += Integer.parseInt(String.valueOf(s), 16);

                array[i / 2] = (byte) value;

                value = 0;

            }

        }

        return array;

    }

    public static byte[] serializeObject(Object obj) throws Exception {
        List<byte[]> fieldBytesList = new ArrayList<>();
        int totalLength = 0;

        // 遍历所有字段
        for (Field field : obj.getClass().getDeclaredFields()) {
            field.setAccessible(true); // 允许访问私有字段

            // 检查是否包含@FixedLength注解
            if (!field.isAnnotationPresent(FixedLength.class)) {
                continue;
            }

            // 获取注解中定义的字节长度
            FixedLength annotation = field.getAnnotation(FixedLength.class);
            int length = annotation.value();

            // 根据字段类型转换字节数组
            Object value = field.get(obj);
            byte[] bytes = convertFieldToBytes(field.getType(), value, length, annotation.paddingByte());

            fieldBytesList.add(bytes);
            totalLength += bytes.length;
        }

        // 合并所有字节数组
        ByteBuffer buffer = ByteBuffer.allocate(totalLength).order(ByteOrder.BIG_ENDIAN); // 默认大端序
        for (byte[] bytes : fieldBytesList) {
            buffer.put(bytes);
        }
        return buffer.array();
    }

    // 处理不同类型字段的字节转换
    private static byte[] convertFieldToBytes(Class<?> type, Object value, int length, byte padByte) {
        if (type == byte.class || type == Byte.class) {
            validateLength(type, length, 1);
            return new byte[] {
                (byte) value
            };
        }
        else if (type == int.class || type == Integer.class) {
            // 整数处理：固定长度（需匹配类型自然长度）
            validateLength(type, length, 4);
            return ByteArrayUtil.int2ByteArray_Little_Endian((int) value);
        }
        else if (type == short.class || type == Short.class) {
            validateLength(type, length, 2);
            return ByteArrayUtil.short2ByteArray_Little_Endian((short) value);
        }
        else if (type == long.class || type == Long.class) {
            validateLength(type, length, 8);
            return ByteArrayUtil.long2ByteArray_Big_Endian((long) value);
        }
        else if (type == float.class || type == Float.class) {
            validateLength(type, length, 4);
            return ByteArrayUtil.float2ByteArray_Little_Endian((float) value);
        }
        else if (type == double.class || type == Double.class) {
            validateLength(type, length, 8);
            return ByteArrayUtil.double2ByteArray_Little_Endian((double) value);
        }
        else if (type == String.class) {
            byte[] src = ((String) value).getBytes(StandardCharsets.UTF_8);
            if (length < 0) {
                return src;
            }
            return adjustLength(src, length, padByte);
        }
        else {
            throw new UnsupportedOperationException("不支持的类型: " + type);
        }
    }

    private static void validateLength(Class<?> type, int actual, int expected) {
        if (actual != expected)
            throw new IllegalArgumentException(type.getSimpleName() + "类型必须为" + expected + "字节");
    }

    private static byte[] adjustLength(byte[] src, int targetLen, byte padByte) {
        byte[] dest = new byte[targetLen];
        int copyLen = Math.min(src.length, targetLen);
        System.arraycopy(src, 0, dest, 0, copyLen);
        Arrays.fill(dest, copyLen, targetLen, padByte);
        return dest;
    }

    public static void main(String[] args) {
        System.out.println(Arrays.toString(long2ByteArray_Big_Endian(23040L)));
    }

}