package com.xhpc.pp.utils.security;

import com.xhpc.pp.utils.HexUtils;

import java.util.Arrays;

public class CRCCalculator {

    public static String ModbusCRC(byte[] pData) {

        int crc = 0xFFFF;
        for (byte pDatum : pData) {
            crc ^= (int) pDatum & 0xFF;   // XOR byte into least sig. byte of crc
            for (int i = 8; i != 0; i--) {   // Loop over each bit
                if ((crc & 0x0001) != 0) {   // If the LSB is set
                    crc >>= 1;               // Shift right and XOR 0xA001
                    crc ^= 0xA001;
                } else                         // Else LSB is not set
                    crc >>= 1;               // Just shift right
            }
        }
        // Revert hi-lo
        crc = ((crc & 0xFF00) >> 8) | ((crc & 0x00FF) << 8);
        return String.format("%04X", crc);
    }

    public static String calcCrc(byte[] data) {

        byte[] data2 = Arrays.copyOfRange(data, 2, data.length - 2);
        return CRCCalculator.ModbusCRC(data2);
    }

    public static String calcCrc(String msg) {

        byte[] data = HexUtils.toBytes(msg);
        assert data != null;
        byte[] data2 = Arrays.copyOfRange(data, 2, data.length);
        return CRCCalculator.ModbusCRC(data2);
    }

    public static int byteArrayToInt(byte[] b) {

        return b[3] & 0xFF |
                (b[2] & 0xFF) << 8 |
                (b[1] & 0xFF) << 16 |
                (b[0] & 0xFF) << 24;
    }

    public static byte[] intToByteArray(int a) {

        return new byte[]{
                (byte) ((a >> 24) & 0xFF),
                (byte) ((a >> 16) & 0xFF),
                (byte) ((a >> 8) & 0xFF),
                (byte) (a & 0xFF)
        };
    }

    public static void main(String[] args) {

        System.out.println(calcCrc("6812001F00416985214589654800000000000000"));
    }

}
