// import system from '../../../common/system';
import errUtil from '../../../utils/error';
import baseUtil from '../../../utils/base';
import tafManager from '../../../manager/tafManager';
import sendManager from './sendManager';
import emitManager from './emitManager';
import ERRORS from '../const/error';
import { ERR_TIMEOUT } from '../../../common/consts';
import pingManager from './pingManager';

const { ERR_TAF_RSP } = ERRORS;

// const TIME_OUT = !system.isProd() ? 1000 * 1000 : 60 * 1000;
const TIME_OUT = 60 * 1000;

class Messager {
  constructor() {
    this.gReqId = Date.now();
  }

  /**
   * PC端消息请求
   * @param {string} funcType 消息类型
   * @param {string} funcName 请求方法名
   * @param {string} reqStr 请求参数
   * @param {*} ui 请求ui
   */
  _dispatch(funcType, funcName, reqStr, ui) {
    return new Promise((resolve, reject) => {
      if (funcName === 'log') {
        sendManager.post({ funcType, funcName, reqStr, ui });
        return;
      }
      const callbackName = `${funcName}Callback_${this.gReqId++}`;

      // 超时计时
      const timer = setTimeout(() => {
        terminate();
        reject(errUtil.pkgErr({ ...ERR_TIMEOUT, callbackName }, `PC端调用[${funcName}]超时`));
      }, TIME_OUT);

      // 设置回调接收
      emitManager.on(callbackName, rspStr => {
        terminate();
        resolve(rspStr);
      }, '', false, true);

      // 终止
      const terminate = () => {
        clearTimeout(timer);
        emitManager.off(callbackName);
      };

      // 发送请求
      sendManager.post({ funcType, funcName, reqStr, ui, callbackName });
    });
  }

  /**
   * PC端消息请求附加 ping 校验
   * @param {string} funcType 消息类型
   * @param {string} funcName 请求方法名
   * @param {string} reqStr 请求参数
   * @param {*} ui 请求ui
   */
  async _dispatchWithPing(...params) {
    await pingManager.ping()
    return await this._dispatch(...params)
  }

  /**
   * Client 类型的消息请求
   * @param {string} funcName 方法名
   * @param {object} req 请求参数
   */
  async dispatch(funcName, req) {
    const reqStr = req ? JSON.stringify(req) : '';
    const rspStr = await this._dispatchWithPing('client', funcName, reqStr);

    const rsp = baseUtil.isString(rspStr) ? JSON.parse(rspStr) : rspStr;
    const { res, data } = rsp || {};
    if (res !== 0) {
      throw errUtil.pkgErr(rspStr);
    }
    return data;
  }

  /**
   * Taf类型的消息请求
   * @param {string} funcName 方法名
   * @param {object} req 请求参数
   * @param {*} RspClazz Taf转换用的Class 
   * @param {*} ui 请求的ui
   */
  async dispatchTaf(funcName, req, RspClazz, ui) {
    let reqStr = '';
    if (req) {
      reqStr = await tafManager.encode(req);
    }

    const rspStr = await this._dispatchWithPing('taf', funcName, reqStr, ui);
    let rsp = null
    let response = null

    try {
      // 信息解码
      rsp = await tafManager.decode(rspStr, RspClazz);
      response = rsp?.response
    } catch (err) {
      // 信息能否转对象
      const info = baseUtil.toObject(rspStr)
      if (!info) throw err
      rsp = info
      response = info
    }

    // 没有返回信息
    if (!response) throw errUtil.pkgErr(ERR_TAF_RSP);

    // 错误信息
    if (response.res !== 0) throw errUtil.pkgErr(response);

    return rsp;
  }

  /**
   * 发送事件到PC端，不考虑返回值
   * @param {string} funcName 
   * @param {object} req 
   */
  emit(funcName, req) {
    return this.dispatch(funcName, req)
  }
}

export default new Messager();
