package com.saki.encode;

import com.saki.QVMProtect;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import java.util.zip.CRC32;
@QVMProtect
public class Code {
    public static final byte[] DEFAULT_KEY = new byte[16];

    public static int[] Byte2Int(byte[] data) {
        if (data.length % 4 != 0)
            return new int[]{};
        int[] i = new int[data.length >> 2];
        for (int p = 0; p < i.length; p++) {
            i[p] = ((data[p * 4] & 0xff) << 24)
                    | ((data[p * 4 + 1] & 0xff) << 16)
                    | ((data[p * 4 + 2] & 0xff) << 8) | data[p * 4 + 3] & 0xff;
        }
        return i;
    }

    public static long Crc(byte[] data) {
        CRC32 crc = new CRC32();
        crc.update(data);
        return crc.getValue();
    }

    public static byte[] Int2Byte(int[] data) {
        byte b[] = new byte[data.length << 2];
        for (int i = 0; i < data.length; i++) {
            b[i * 4 + 0] = (byte) (data[i] >> 24);
            b[i * 4 + 1] = (byte) (data[i] >> 16);
            b[i * 4 + 2] = (byte) (data[i] >> 8);
            b[i * 4 + 3] = (byte) (data[i] >> 0);
        }
        return b;
    }

    public static byte[] MD5(byte[] bs) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(bs);
            return md.digest();
        } catch (NoSuchAlgorithmException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        return new byte[]{};
    }
    public static byte[] QQTEAdecrypt(byte in[],byte[] key){
        return QQTEAdecrypt(in,key,16);
    }
    public static byte[] QQTEAdecrypt(byte in[], byte[] key,int loops) {
        // 因为QQ消息加密之后至少是16字节，并且肯定是8的倍数，这里检查这种情况
        int len = in.length;
        int end = len % 8;
        if (end != 0) {
            byte[] bin = new byte[len + 8 - end];
            System.arraycopy(in, 0, bin, 0, in.length);
            in = bin;
            len = in.length;
        }
        if ((len % 8 != 0) || (len < 16)) {
            return new byte[]{};
        }
        byte[] Out = new byte[len];
        byte[] src = new byte[8];
        byte[] pre = null;
        byte[] Crypt = new byte[8];
        for (int i = 0; i < len; i += 8) {
            // 拷贝待解密数组
            System.arraycopy(in, i, src, 0, 8);// 即最终密文
            if (pre == null) {
                pre = TEA.decrypt(src, key,loops);// 前8个字节直接解密得到明文
                System.arraycopy(pre, 0, Crypt, 0, 8);
            } else {
                for (int p = 0; p < 8; p++) {
                    Crypt[p] = (byte) (src[p] ^ pre[p]);// 获取加密之后的结果
                }
                pre = TEA.decrypt(Crypt, key,loops);// 解密,取得结果
                for (int p = 0; p < 8; p++) {
                    Crypt[p] = (byte) (pre[p] ^ in[i - 8 + p]);
                }
            }
            System.arraycopy(Crypt, 0, Out, i, 8);
        }
        // 计算明文位置
        int pos = Out[0] & 0x07;
        // 明文长度
        len = Out.length - pos - 10;
        // 明文
        byte[] resault = new byte[len - (end == 0 ? end : 8 - end)];
        System.arraycopy(Out, pos + 3, resault, 0, resault.length);
        return resault;
    }
    public static byte[] QQTEAencrypt(byte[] in,byte[] key){
        return QQTEAencrypt(in,key,16);
    }
    public static byte[] QQTEAencrypt(byte plain[], byte key[],int loops) {
        Random random = new Random();
        // 计算数据开头
        int pos = (plain.length + 10) % 8;
        if (pos != 0)
            pos = 8 - pos;
        // 计算数据长度
        int len = plain.length + 10 + pos;
        byte resault[] = new byte[len];
        // 开头保存pos
        resault[0] = (byte) (0xad & 0xf8 | pos);
        // 填充随机数到pos+2
        for (int i = 1; i <= pos + 2; i++) {
            resault[i] = (byte) (random.nextInt(256) & 0xff);
        }
        // 明文填充
        System.arraycopy(plain, 0, resault, pos + 3, plain.length);
        // 剩余字节默认为0
        //
        byte wait[] = new byte[8];// 准备加密的明文
        byte Crypted[] = null;// 加密之后的密文
        byte preHand[] = new byte[8];// 前一轮的操作结果
        byte handed[] = new byte[8];// 操作结果
        byte out[] = new byte[resault.length];// 返回的密文

        // 遍历整个字节组，进行加密
        for (int i = 0; i < resault.length; i += 8) {
            System.arraycopy(resault, i, wait, 0, 8);// 拷贝8个字节的明文
            if (Crypted == null) {
                Crypted = TEA.encrypt(wait, key,loops);
                System.arraycopy(resault, 0, preHand, 0, 8);
            } else {
                // 明文与前一轮最终加密结果进行操作
                for (int p = 0; p < 8; p++) {
                    handed[p] = (byte) (wait[p] ^ Crypted[p]);
                }
                // 加密操作结果
                Crypted = TEA.encrypt(handed, key,loops);
                for (int p = 0; p < 8; p++) {
                    // 与前一轮的操作结果进行操作，的最终加密结果
                    Crypted[p] = (byte) (Crypted[p] ^ preHand[p]);
                }
                System.arraycopy(handed, 0, preHand, 0, 8);
            }
            System.arraycopy(Crypted, 0, out, i, 8);
        }
        // 加密
        return out;
    }
}
