
import { ConfigLoaderNet, ConfigLoaderLocal, } from '../loader'
import { log4js } from '../log4js/logger'
import { ConfigRequire } from '../models/ConfigRequire'
import { Singleton } from 'typescript-ioc'

@Singleton
export class ConfigClient {

    private loaderLocal?: ConfigLoaderLocal
    private loaderNet?: ConfigLoaderNet
    private currentConfigData = new Map<string, any>()
    private init: boolean = false

    async initClient(configRequires: Array<ConfigRequire>) {
        if (this.init) {
            return
        }
        const meEnv = process.env['KT_ME_ENV'] || ''
        const meEnvKey = process.env['KT_ME_ENV_KEY'] || ''
        const configLocalPath = process.env['KT_CONFIG_LOCAL_PATH'] || ''
        const configServerUrl = process.env['KT_CONFIG_SERVER_URL'] + '/getConfigFile/json'
        if (!meEnv || meEnv.length <= 0) {
            log4js.error('初始化配置中心客户端失败，KT_ME_ENV 未设置')
            return;
        }
        if (!meEnvKey || meEnvKey.length <= 0) {
            log4js.error('初始化配置中心客户端失败，KT_ME_ENV_KEY 未设置')
            return;
        }

        this.loaderLocal = new ConfigLoaderLocal(meEnv, meEnvKey, configLocalPath, configServerUrl);
        this.loaderNet = new ConfigLoaderNet(meEnv, meEnvKey, configLocalPath, configServerUrl);
        await this.pullConfigFiles(configRequires);
        this.init = true;
    }

    /**
     * 拉取配置文件
     */
    private async pullConfigFiles(configRequires: Array<ConfigRequire>) {
        if (configRequires.length === 0) {
            return
        }
        //配置数据存入map中
        const configData = new Map<string, any>();
        //先从本地加载
        try {
            await this.loaderLocal!!.load(configData, configRequires);
        } catch (e) {
            console.error(e)
        }
        //再从配置中心加载 
        try {
            await this.loaderNet!!.load(configData, configRequires);
        } catch (e) {
            console.error(e)
        }
        if (configData.size > 0) {
            this.currentConfigData = configData;
        }
        this.putConfigProperties(configData)

    }


    /**
     * 将配置内容塞入到环境变量中
     * @param configData 
     */
    private putConfigProperties(configData: Map<string, any>) {
        configData.forEach((value, key) => {
            process.env[key] = value
        })
    }

    /**
     * 获取配置内容
     * @param key 配置Key名
     */
    getConfig(key: string): any {
        return this.currentConfigData.get(key)
    }


    /**
     * 获取所有配置内容
     */
    getAllConfig(): object {
        return Array.from(this.currentConfigData.entries()).reduce((main, [key, value]) => ({ ...main, [key]: value }), {})
    }
}