import { parseString } from 'xml2js';
import { Md5 } from 'ts-md5';

export default class QuickAsy {

    /**
     * 解码函数
     * @param strEncode 加密字符串
     * @param keys 解密密钥 (在游戏中通常是 callback_key)
     * @returns 解码后的字符串
     */
    static decode(strEncode: string, keys: string): string {
        if (!strEncode) {
            return strEncode;
        }

        const list = strEncode.match(/\d+/g);
        if (list && list.length > 0) {
            const keyBytes = QuickAsy.getBytes(keys);
            const data: number[] = [];

            for (let i = 0; i < list.length; i++) {
                const keyVar = keyBytes[i % keyBytes.length];
                data[i] = parseInt(list[i]) - (0xff & keyVar);
            }

            return QuickAsy.toStr(data);
        } else {
            return strEncode;
        }
    }

    /**
     * 生成游戏同步签名
     * @param params 参数对象
     * @param callbackKey 回调密钥
     * @returns 签名字符串
     */
    static getSign(params: { nt_data: string, sign: string }, callbackKey: string): string {
        return QuickAsy.md5(params.nt_data + params.sign + callbackKey);
    }

    /**
     * 替换MD5
     * @param md5 传入的MD5值
     * @returns 替换后的MD5值
     */
    static replaceMD5(md5: string): string {
        md5 = md5.toLowerCase();
        const bytes = QuickAsy.getBytes(md5);
        const len = bytes.length;

        if (len >= 23) {
            let change = bytes[1];
            bytes[1] = bytes[13];
            bytes[13] = change;

            let change2 = bytes[5];
            bytes[5] = bytes[17];
            bytes[17] = change2;

            let change3 = bytes[7];
            bytes[7] = bytes[23];
            bytes[23] = change3;
        } else {
            return md5;
        }

        return QuickAsy.toStr(bytes);
    }

    /**
     * 将字符串转换为字节数组
     * @param string 字符串
     * @returns 字节数组
     */
    private static getBytes(string: string): number[] {
        const bytes: number[] = [];
        for (let i = 0; i < string.length; i++) {
            bytes.push(string.charCodeAt(i));
        }
        return bytes;
    }

    /**
     * 将字节数组转换为字符串
     * @param bytes 字节数组
     * @returns 转换后的字符串
     */
    private static toStr(bytes: number[]): string {
        return String.fromCharCode(...bytes);
    }

    /**
     * 计算 MD5 哈希值 (假设我们有一个 md5 函数)
     * @param str 输入字符串
     * @returns MD5 哈希值
     */
    private static md5(str: string): string {
        // 假设有一个全局的 `md5` 函数可以使用
        return Md5.hashStr(str);
    }

    static parseXmlToObject<T>(xml: string): T {
    let result: T;
    parseString(xml, (err, parsedResult) => {
        if (err) {
            console.error('Error parsing XML:', err);
            throw err;
        }
        result = parsedResult as T;
    });

    // 由于 parseString 是异步回调的，所以需要在这里做等待处理
    if (!result) {
        throw new Error('Parsing failed');
    }
    return result;
    }
}
