package com.cscn;

/**
 * 辅助工具：装载/存储、位运算、线性变换、打印等。
 */
public final class Zuc256Util {

    private Zuc256Util() {}

    /** 辅助方法：将字节数组转换为32位整数 */
    public static int getU32(byte[] p, int offset) {
        return ((p[offset] & 0xFF) << 24) |
                ((p[offset + 1] & 0xFF) << 16) |
                ((p[offset + 2] & 0xFF) << 8) |
                (p[offset + 3] & 0xFF);
    }

    /** 辅助方法：将32位整数转换为字节数组 */
    public static void putU32(byte[] p, int offset, int v) {
        p[offset] = (byte) (v >> 24);
        p[offset + 1] = (byte) (v >> 16);
        p[offset + 2] = (byte) (v >> 8);
        p[offset + 3] = (byte) v;
    }

    // === 31/32 位运算 ===

    /** 31位加法 */
    public static int add31(int a, int b) {
        long sum = (long)a + b;
        return (int) ((sum & 0x7FFFFFFF) + (sum >> 31));
    }

    /** 31位旋转 */
    public static int rot31(int a, int k) {
        return ((a << k) | (a >>> (31 - k))) & 0x7FFFFFFF;
    }

    /** 32位旋转 */
    public static int rot32(int a, int k) {
        return (a << k) | (a >>> (32 - k));
    }

    /**
     * L1函数
     */
    public static int L1(int x) {
        return x ^ rot32(x, 2) ^ rot32(x, 10) ^ rot32(x, 18) ^ rot32(x, 24);
    }

    /**
     * L2函数
     */
    public static int L2(int x) {
        return x ^ rot32(x, 8) ^ rot32(x, 14) ^ rot32(x, 22) ^ rot32(x, 30);
    }

    /** 创建31位无符号整数 */
    public static int makeU31(int a, int b, int c, int d) {
        return (((a & 0xFF) << 23) |
                ((b & 0xFF) << 16) |
                ((c & 0xFF) << 8) |
                (d & 0xFF)) & 0x7FFFFFFF;
    }

    /** 创建32位无符号整数 */
    public static int makeU32(int a, int b, int c, int d) {
        return ((a & 0xFF) << 24) |
                ((b & 0xFF) << 16) |
                ((c & 0xFF) << 8) |
                (d & 0xFF);
    }


    /** 提取IV */
    public static void extractIv(byte[] input25Byte, byte[] output23Byte) {
        if (input25Byte == null || output23Byte == null) return;

        // 复制前17字节
        System.arraycopy(input25Byte, 0, output23Byte, 0, 17);

        // 处理剩余8字节
        byte[] src = new byte[8];
        for (int i = 0; i < 8; i++) {
            src[i] = (byte) (input25Byte[17 + i] & 0x3F);
        }

        output23Byte[17] = (byte) ((src[0] << 2) | (src[1] >>> 4));
        output23Byte[18] = (byte) (((src[1] & 0x0F) << 4) | (src[2] >>> 2));
        output23Byte[19] = (byte) (((src[2] & 0x03) << 6) | src[3]);
        output23Byte[20] = (byte) ((src[4] << 2) | (src[5] >>> 4));
        output23Byte[21] = (byte) (((src[5] & 0x0F) << 4) | (src[6] >>> 2));
        output23Byte[22] = (byte) (((src[6] & 0x03) << 6) | src[7]);
    }

    /** 打印十六进制（调试用，TODO 生产/JC 环境可移除） */
    public static void printHex(String label, byte[] data, int len) {
        System.out.print(label + ": ");
        for (int i = 0; i < len; i++) {
            System.out.printf("%02x ", data[i] & 0xFF);
        }
        System.out.println();
    }
}
