package com.yeechart.dotMatrix.crc;

/**
 * xzp 配置暂时为默认 后续有需要可增加自定义接口实现自定义配置
 * 暂不支持配置多项式公式,当前使用的为 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
 * 自定义 CRC32工具类
 */
public class CustomCRC32Util {
    private static final int WIDTH = 32;//宽度位数
    private static final int POLYNOMIAL = 0x04C11DB7;//多项式POLY(HEX)
    private static final long INITIAL_VALUE = 0xFFFFFFFFL;//初始值
    private static final long FINAL_XOR_VALUE = 0xFFFFFFFFL;//结果异或值
    private static final boolean REVERSE_DATA = true;//数据反转
    private static final boolean REVERSE_OUTPUT = true;//输出反转

    public static long calculateCRC32(byte[] bytes) {
        long crc = INITIAL_VALUE;

        if (REVERSE_DATA) {
            bytes = reverseBytes(bytes);
        }

        for (byte b : bytes) {
            crc ^= ((long) b) << (WIDTH - 8);
            for (int j = 0; j < 8; j++) {
                if ((crc & 0x80000000L) != 0) {
                    crc = (crc << 1) ^ POLYNOMIAL;
                } else {
                    crc <<= 1;
                }
            }
        }

        if (REVERSE_OUTPUT) {
            crc = reverseBits(crc);
        }

        return crc ^ FINAL_XOR_VALUE;
    }

    private static byte[] reverseBytes(byte[] bytes) {
        byte[] reversedBytes = new byte[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            reversedBytes[i] = reverseBits(bytes[i]);
        }
        return reversedBytes;
    }

    private static byte reverseBits(byte b) {
        int reversed = 0;
        for (int i = 0; i < 8; i++) {
            reversed = (reversed << 1) | ((b >> i) & 1);
        }
        return (byte) reversed;
    }

    private static long reverseBits(long value) {
        long reversed = 0;
        for (int i = 0; i < WIDTH; i++) {
            reversed = (reversed << 1) | ((value >> i) & 1);
        }
        return reversed;
    }
}
