// 假设这些类型和函数在前端可以找到替代实现
type Dictionary<T> = { [key: string]: T };
type Tuple<T1, T2> = [T1, T2];
type Func<T, R> = (arg: T) => R;

// 假设这些配置和工具类在前端有相应的实现
class PlatformSettings {
    static EncryptsKey: string;
    static Encoding: {
        GetBytes: (str: string) => Uint8Array;
        GetString: (bytes: Uint8Array) => string;
    };
}

class ConfigManager {
    static GetInstance(): ConfigManager {
        return new ConfigManager();
    }
    GetConfigValue(key: string, type: any): string {
        // 实现配置获取逻辑
        return '';
    }
}

// 假设 MsgEncryptionKitLib 在前端有相应的实现
namespace MsgEncryptionKitLib {
    export class CryptoAgent {
        GenSymKey(): string {
            // 实现生成对称密钥逻辑
            return '';
        }
        GenServerRandomRequest(genSymKey: string, publicKey: string): string {
            // 实现生成服务器随机请求逻辑
            return '';
        }
        ExchangeKey(genSymKey: string, serverRandom: string): string {
            // 实现密钥交换逻辑
            return '';
        }
        EncryptMessage(key: string, msg: string, publicKey: string): string {
            // 实现加密逻辑
            return '';
        }
        DecryptMessage(key: string, msg: string): string {
            // 实现解密逻辑
            return '';
        }
    }
}

// 加解密模式枚举
enum Mode {
    Des2FixKey = 0,
    Sm2 = 1,
}

export default class EncrypDecryptHelper {



    private static _instance: EncrypDecryptHelper;
    private KEY = PlatformSettings.EncryptsKey;
    private defaultMode: Mode;
    private publicKeyFileInfo = null;// new FileInfo('Devices/Cfca/Platform.PublicKey.sm2');//TODO:加密
    private msgEncrypt: MsgEncryptionKitLib.CryptoAgent | null = null;
    private publicKey = '';
    private genSymKey = '';
    private clientKey = '';
    private serverHandle = '';

    private constructor() {
        this.initDefaultMode();
    }

    static get Instance(): EncrypDecryptHelper {
        if (!this._instance) {
            this._instance = new EncrypDecryptHelper();
        }
        return this._instance;
    }

    get DefaultMode(): Mode {
        return this.defaultMode;
    }

    private initDefaultMode() {
        const configValue = ConfigManager.GetInstance().GetConfigValue('EncryptMode', null);
        if (!Object.values(Mode).includes(parseInt(configValue))) {
            this.defaultMode = Mode.Des2FixKey;
        } else {
            this.defaultMode = parseInt(configValue) as Mode;
        }
    }

    Init(mode: Mode, init: Func<Dictionary<string>, Dictionary<string>>): boolean | null {
        if (mode !== this.defaultMode) return null;
        switch (mode) {
            case Mode.Des2FixKey:
                break;
            case Mode.Sm2:
                const exchange: Func<string, Tuple<string, string>> = (rqt) => {
                    const rst = init({ ServerRandomRequest: rqt });
                    return [rst['ServerRandom'], rst['ServerHandle']];
                };
                if (!this.Sm2ExchangeKey(exchange)) {
                    this.defaultMode = Mode.Des2FixKey;
                }
                break;
            default:
                break;
        }
        return true;
    }
    //TODO 加密方式
    static Encrypt(msgByte: Uint8Array<ArrayBuffer>, arg1: boolean): Uint8Array<ArrayBuffer> {
        throw new Error('Method not implemented.');
    }
    static Decrypt(message: Uint8Array<ArrayBuffer>, arg1: boolean): Uint8Array<ArrayBuffer> {
        throw new Error('Method not implemented.');
    }

    Encrypt(msg: Uint8Array, toServer = false): Uint8Array {
        let data: Uint8Array | null = null;
        switch (this.defaultMode) {
            case Mode.Des2FixKey:
                data = this.DesEncryptFixKey(msg);
                break;
            case Mode.Sm2:
                data = this.Sm2Encrypt(msg, toServer);
                break;
            default:
                throw new Error(`不支持的加解方式：${this.defaultMode}`);
        }
        return data;
    }

    Decrypt(msg: Uint8Array, toServer = false): Uint8Array {
        let data: Uint8Array | null = null;
        switch (this.defaultMode) {
            case Mode.Des2FixKey:
                data = this.DesDecryptFixKey(msg);
                break;
            case Mode.Sm2:
                data = this.Sm2Decrypt(msg, toServer);
                break;
            default:
                throw new Error(`不支持的加解密方式：${this.defaultMode}`);
        }
        return data;
    }

    private DesEncryptFixKey(msg: Uint8Array): Uint8Array {
        const byKey = PlatformSettings.Encoding.GetBytes(this.KEY);
        const IV = new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
        // 这里需要使用前端可用的 DES 加密库实现
        const encrypted = new Uint8Array();
        return PlatformSettings.Encoding.GetBytes(btoa(String.fromCharCode.apply(null, encrypted)));
    }

    private DesDecryptFixKey(msg: Uint8Array): Uint8Array {
        const byKey = PlatformSettings.Encoding.GetBytes(this.KEY);
        const IV = new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF]);
        const inputByteArray = Uint8Array.from(atob(PlatformSettings.Encoding.GetString(msg)).split('').map(c => c.charCodeAt(0)));
        // 这里需要使用前端可用的 DES 解密库实现
        const decrypted = new Uint8Array();
        return decrypted;
    }

    private Sm2Init(): boolean {
        if (!this.msgEncrypt) {
            try {
                // 这里需要使用前端可用的文件读取方式实现
                this.publicKey = '';
                this.msgEncrypt = new MsgEncryptionKitLib.CryptoAgent();
                this.genSymKey = this.msgEncrypt.GenSymKey();
            } catch (error) {
                return false;
            }
        }
        return true;
    }

    private Sm2ExchangeKey(exChange: Func<string, Tuple<string, string>>): boolean {
        if (this.Sm2Init()) {
            if (this.clientKey) return true;
            const rqt = this.msgEncrypt!.GenServerRandomRequest(this.genSymKey, this.publicKey);
            const [serverRandom, serverHandle] = exChange(rqt);
            this.clientKey = this.msgEncrypt!.ExchangeKey(this.genSymKey, serverRandom);
            this.serverHandle = serverHandle;
            return true;
        }
        return false;
    }

    private Sm2Encrypt(msg: Uint8Array, exChange = true): Uint8Array {
        if (!this.Sm2Init()) return new Uint8Array();
        const key = exChange && this.clientKey ? this.clientKey : this.genSymKey;
        const rst = this.msgEncrypt!.EncryptMessage(key, btoa(String.fromCharCode.apply(null, msg)), this.publicKey);
        if (exChange) {
            const prefix = `SM2${this.serverHandle.length.toString().padStart(4, '0')}${this.serverHandle}`;
            return PlatformSettings.Encoding.GetBytes(prefix + rst);
        }
        return PlatformSettings.Encoding.GetBytes(rst);
    }

    private Sm2Decrypt(msg: Uint8Array, exChange = true): Uint8Array {
        if (!this.Sm2Init()) return new Uint8Array();
        const key = exChange && this.clientKey ? this.clientKey : this.genSymKey;
        const rst = this.msgEncrypt!.DecryptMessage(key, btoa(String.fromCharCode.apply(null, msg)));
        return Uint8Array.from(atob(rst).split('').map(c => c.charCodeAt(0)));
    }
}

export { EncrypDecryptHelper, Mode };
