import { ConfigRequire } from '../models/ConfigRequire'
import { ConfigLoader } from './ConfigLoader'
import HttpUtil from '../utils/HttpUtil'
import { log4js } from '../log4js/logger'

import * as fs from 'fs'
import * as util from 'util'

export class ConfigLoaderNet extends ConfigLoader {

    /**
     * 加载配置
     * @param configData 配置内容
     */
    async load(configData: Map<string, any>, configRequires: Array<ConfigRequire>) {
        if (!configRequires || configRequires.length == 0) {
            return
        }
        for (const configRequire of configRequires) {
            await this.pullConfigFile(configData, configRequire)
        }
    }


    /**
     * 从远程配置中心拉取配置内容
     * @param configData 配置中心加载的配置内容
     * @param configRequire 依赖配置版本，配置代码
     * @param retry 重试次数
     */
    private async pullConfigFile(configData: Map<string, any>, configRequire: ConfigRequire, retry: number = 1) {
        if (retry > 3) {
            return; //超过3就不重试了
        }
        const params = {} as any
        params["meEnv"] = this.meEnv;
        params["meEnvKey"] = this.meEnvKey;
        params["configCode"] = configRequire.configCode;
        params["version"] = configRequire.version
        log4js.debug('准备加载配置文件--->ENV:%s ,configCode:%s,version：%s ,configServer: %s', this.meEnv, configRequire.configCode, configRequire.version,this.configServerUrl!!)
        const response = await HttpUtil.get(this.configServerUrl!!, params).catch(error => {
            log4js.error('加载配置中心配置异常--->ENV:%s ,configCode:%s,version：%s, error :%j', this.meEnv, configRequire.configCode, configRequire.version, error)
        });
        log4js.debug('加载配置文件完成--->ENV:%s ,configCode:%s,version：%s ,response: %j', this.meEnv, configRequire.configCode, configRequire.version,response)
        let isSuccess = false;
        if (response && response.status === 200) {
            const opResult = response.data
            if (opResult.code !== 2000) {
                throw new Error('加载配置错误' + opResult.message)
            }
            const config = opResult.data
            isSuccess = true
            log4js.debug('加载配置中心配置成功--->ENV:%s ,configCode:%s,version：%s, result :%j', this.meEnv, configRequire.configCode, configRequire.version, config)
            if (config) {
                const keys = Object.keys(config)
                keys.forEach(key => {
                    configData.set(key, config[key])
                })
                await this.saveToFile(configRequire, config)
            }
        }else{
            log4js.error('加载配置中心配置失败--->ENV:%s ,configCode:%s,version：%s, response :%j', this.meEnv, configRequire.configCode, configRequire.version, response)
        }

        if (!isSuccess) {
            await this.pullConfigFile(configData, configRequire, ++retry)
        }
    }

    /**
     * 配置文件保存到本地
     * @param configRequire 
     * @param config 
     */
    async saveToFile(configRequire: ConfigRequire, config: any) {
        if (!this.configLocalPath || this.configLocalPath.length == 0) {
            return
        }
        const fs_writeFile = util.promisify(fs.writeFile)
        const path = this.assembleFilePath(configRequire)
        await fs_writeFile(path, JSON.stringify(config));
    }


}