// 假设 EncrypDecryptHelper 类的实现
class EncrypDecryptHelper {
    static Instance = new EncrypDecryptHelper();

    DesDecryptFixKey(data: Uint8Array): Uint8Array {
        // 实现解密逻辑
        return data;
    }

    DesEncryptFixKey(data: Uint8Array): Uint8Array {
        // 实现加密逻辑
        return data;
    }
}

// 配置文件类型枚举
enum ConfigType {
    System,
    Client,
    User
}

class ConfigManager {
    private static instance: ConfigManager;
    private readonly _dirName = "Config";
    private readonly _clientFileInfo = `${this._dirName}/Platform.Client.Config`;
    private _clientDictionary: { [key: string]: string } = {};
    private readonly _systemFileInfo = `${this._dirName}/Platform.System.Config`;
    private _systemDictionary: { [key: string]: string } = {};
    private readonly _userFileInfo = `${this._dirName}/Platform.User.Config`;
    private _userDictionary: { [key: string]: string } = {};

    private constructor() { }

    public static GetInstance(): ConfigManager {
        if (!this.instance) {
            this.instance = new ConfigManager();
        }
        return this.instance;
    }

    public async LoadConfig(configType: ConfigType, isEncryptedFile = false): Promise<boolean> {
        switch (configType) {
            case ConfigType.System:
                return this.Load(this._systemFileInfo, this._systemDictionary, isEncryptedFile);
            case ConfigType.Client:
                return this.Load(this._clientFileInfo, this._clientDictionary);
            case ConfigType.User:
                return this.Load(this._userFileInfo, this._userDictionary, isEncryptedFile);
            default:
                return false;
        }
    }

    private async Load(from: string, to: { [key: string]: string }, isEncryptedFile = false): Promise<boolean> {
        try {
            const response = await fetch(from);
            if (response.ok) {
                const data = new Uint8Array(await response.arrayBuffer());
                let decryptedData = isEncryptedFile ? EncrypDecryptHelper.Instance.DesDecryptFixKey(data) : data;
                const xmlString = new TextDecoder().decode(decryptedData);
                const parser = new DOMParser();
                const doc = parser.parseFromString(xmlString, "application/xml");
                const elementCollection = doc.documentElement.children;
                for (let i = 0; i < elementCollection.length; i++) {
                    const element = elementCollection[i];
                    const elementKey = element.getAttribute("key");
                    const elementValue = element.getAttribute("value");
                    if (!elementKey) break;
                    if (to.hasOwnProperty(elementKey)) {
                        to[elementKey] = elementValue || "";
                    } else {
                        to[elementKey] = elementValue || "";
                    }
                }
                return true;
            } else {
                return false;
            }
        } catch (error) {
            return false;
        }
    }

    public async SaveConfig(configType: ConfigType, isEncryptedFile = false): Promise<string | null> {
        switch (configType) {
            case ConfigType.System:
                return this.Save(this._systemDictionary, this._systemFileInfo, isEncryptedFile);
            case ConfigType.Client:
                return this.Save(this._clientDictionary, this._clientFileInfo);
            case ConfigType.User:
                return this.Save(this._userDictionary, this._userFileInfo, isEncryptedFile);
            default:
                return null;
        }
    }

    private async Save(from: { [key: string]: string }, to: string, isEncryptedFile = false): Promise<string | null> {
        const xmlDoc = document.implementation.createDocument(null, "elements");
        xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", 'version="1.0" encoding="UTF-8"'));
        for (const [key, value] of Object.entries(from)) {
            const element = xmlDoc.createElement("element");
            element.setAttribute("key", key);
            element.setAttribute("value", value);
            xmlDoc.documentElement.appendChild(element);
        }
        const serializer = new XMLSerializer();
        const xmlString = serializer.serializeToString(xmlDoc);
        let data = new TextEncoder().encode(xmlString);
        if (isEncryptedFile) {
            data = EncrypDecryptHelper.Instance.DesEncryptFixKey(data);
        }
        try {
            await fetch(to, {
                method: "PUT",
                body: data
            });
            return to;
        } catch (error) {
            return null;
        }
    }

    public GetConfigValue(key: string, configType: ConfigType): string {
        let ret = "";
        if (key) {
            switch (configType) {
                case ConfigType.System:
                    if (this._systemDictionary.hasOwnProperty(key)) {
                        ret = this._systemDictionary[key];
                    }
                    break;
                case ConfigType.Client:
                    if (this._clientDictionary.hasOwnProperty(key)) {
                        ret = this._clientDictionary[key];
                    }
                    break;
                case ConfigType.User:
                    if (this._userDictionary.hasOwnProperty(key)) {
                        ret = this._userDictionary[key];
                    }
                    break;
                default: break;
            }
        }
        return ret;
    }

    public SetConfigValue(key: string, value: string, configType: ConfigType): boolean {
        let ret = false;
        if (key) {
            switch (configType) {
                case ConfigType.System:
                    if (this._systemDictionary.hasOwnProperty(key)) {
                        this._systemDictionary[key] = value;
                    } else {
                        this._systemDictionary[key] = value;
                    }
                    ret = true;
                    break;
                case ConfigType.Client:
                    if (this._clientDictionary.hasOwnProperty(key)) {
                        this._clientDictionary[key] = value;
                    } else {
                        this._clientDictionary[key] = value;
                    }
                    ret = true;
                    break;
                case ConfigType.User:
                    if (this._userDictionary.hasOwnProperty(key)) {
                        this._userDictionary[key] = value;
                    } else {
                        this._userDictionary[key] = value;
                    }
                    ret = true;
                    break;
                default: break;
            }
        }
        return ret;
    }
}

export { ConfigManager, ConfigType };
