import { ConfigLoaderNet, ConfigLoaderLocal } from '../loader';
import { logger } from 'mslib';
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) {
      logger.error('初始化配置中心客户端失败，KT_ME_ENV 未设置');
      return;
    }
    if (!meEnvKey || meEnvKey.length <= 0) {
      logger.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 }),
      {}
    );
  }
}
