import JSONObject from "../../expression/instances/JSONObject";
import ServiceException from "../../expression/exception/ServiceException";
import LogicConsole from "../../expression/instances/LogicConsole";
import ExpressionRunner from "../../expression/ExpressionRunner";
import { indexedDB } from '../../utils/indexedDB'

export default class LogicRunner {

  private static logicConsoleInstance: LogicConsole = new LogicConsole();

  /**
   * 是否存在指定名称的Logic资源
   *
   * @param logicName Logic名称
   * @return 是否存在
   */
  public static has(logicName: string): boolean {
    return LogicRunner.getLogic(logicName, false, (result: any) => {
      return result != null;
    });
  }

  /**
   * 执行Logic
   *
   * @param logicName      Logic名称
   * @param param          参数
   * @return 执行结果
   */
  public static run(logicName: string, param: JSONObject | Object) : any {
    // 获取Logic资源
    const source = LogicRunner.getLogic(logicName, false, (result: any) => {
      return result;
    });
    if (source == null) {
      throw new ServiceException("Logic资源" + logicName + "未找到", 400)
    }
    const logicLog = LogicConsole.createLogger('logic.' + logicName)
    logicLog.info("执行Logic[{}]，params: {}", logicName, param)
    // 附加用户注册的对象到业务逻辑中
    const plugins = new JSONObject();
    plugins.put("data", param);
    plugins.put("log", logicLog);
    plugins.put("logic", LogicRunner.prototype);
    return LogicRunner.runExpression(source, plugins);
  }

  /**
   * 执行原生表达式
   *
   * @param source 表达式内容
   * @param params 参数
   * @return 执行结果
   */
  private static runExpression(source: string, params: JSONObject) : any {
    return ExpressionRunner.run(source, params)
  }

  private static getLogic(logicName: string, isDev: boolean, callback: Function) : any {
    let apiPre = '/api/'
    if (isDev) {
      apiPre = '/devApi/'
    }
    const serviceName = process.env.VUE_APP_SYSTEM_NAME
    const getConfigUrl = apiPre + serviceName + '/logic/openapi/getLiuliConfiguration'
    // body 增加 shouldParseConfig: false，获取业务逻辑时不触发服务端编译
    indexedDB.getByWeb(logicName, getConfigUrl, { configName: logicName, shouldParseConfig: false }, callback)
  }
}
