import { Injectable } from "../container/Injectable";
import ClassName from "../container/ClassName";
import Logger from "./Logger";
import defaultConfig, { Config, isNotified } from "./config/defaultConfig";
import MsgWrapper from "./utils/MsgWrapper";
import { InjectionKey } from "vue";

@Injectable()
@ClassName('LocalConfigWrapper')
export default class LocalConfigWrapper {

    constructor(
        private readonly logger: Logger,
        private readonly msgWrapper: MsgWrapper,
    ) {
    }

    public get config(): Config {
        const _this = this;
        const str2code = (str: string): number[] => {
            let code = [];
            for (let i = 0; i < str.length; i++) {
                code.push(str.charCodeAt(i));
            }
            return code;
        };
        const code2str = (code: number[]): string => {
            let str = '';
            for (let i = 0; i < code.length; i++) {
                str += String.fromCharCode(code[i]);
            }
            return str;
        };
        return new Proxy(_this.Local, {
            get(target: Config, prop: string) {
                let value = target[prop] ?? defaultConfig[prop];
                if (prop === 'autoLoginPwd') {
                    let jsonObj;
                    try {
                        jsonObj = JSON.parse(window.atob(value));
                    } catch (e) {
                        jsonObj = [];
                    }
                    value = code2str(jsonObj);
                }
                return value;
            },
            set(target: Config, prop: string, value: any): boolean {
                let config = target;
                let preVal = config[prop];
                if (prop === 'autoLoginPwd') {
                    value = window.btoa(JSON.stringify(str2code(value)));
                }
                if (preVal !== value) {
                    config[prop] = value;
                    _this.setLocal(config);
                    let msg = `[${ prop }]值变更 ${ preVal }->${ value }`;
                    _this.logger.info(msg);
                    if (isNotified(prop)) {
                        _this.msgWrapper.create(msg);
                    }
                }
                return true;
            }
        })
    }

    /**
     * 从localstorage解析返回配置对象
     * @private
     */
    private get Local(): Config {
        let config: Config;
        try {
            config = JSON.parse(localStorage.getItem('wh_trans_settings')) ?? defaultConfig;
        } catch (e) {
            this.logger.error('配置解析失败, 载入默认');
            config = defaultConfig;
            localStorage.setItem('wh_trans_settings', JSON.stringify(defaultConfig));
        }
        return config;
    }

    private setLocal(config: Config) {
        localStorage.setItem('wh_trans_settings', JSON.stringify(config));
    }
}

export const LocalConfigWrapperKey = Symbol() as InjectionKey<LocalConfigWrapper>;
