import EventManager from './eventManager';
import TapableManager from './tapableManager';
import logger from '../common/logger';
import { EVENT_NAME_NULL, EVENT_CALLBACK_INVALID, EVENT_UNSUPPORT } from '../common/consts';
import baseUtil from '../utils/base';
import errUtil from '../utils/error'

/**
 * 系统事件管理器初始类
 * 每个平台可继承并重写
 */
export default class NativeEventManager {

  constructor(opt) {
    this._opt = opt || {};
    this._eventer = new EventManager();
    this._hook = new TapableManager();

    const { supportEvents } = this._opt
    this._sEvents = supportEvents
  }

  /**
   * 注入回调
   * @callback InjectCallback
   * @param {string} eventName 方法名
   * @param {Function} callback 回调
   * @param {Object} [options] 
   */
  /**
   * 参数处理回调
   * @callback ReducerCallback
   * @param {string} eventName 方法名
   * @param {Object} params 初始参数 
   */
  /**
   * 注册拦截器
   * @param {Object} opt 传入参数
   * @param {ReducerCallback} [opt.resReducer] 事件触发返回参数处理， 必须返回 { eventName: string, params: Object }
   * @param {InjectCallback} [opt.beforeOn] 注册事件前触发
   * @param {InjectCallback} [opt.afterOn] 注册事件后触发
   * @param {InjectCallback} [opt.beforeOff] 取消注册事件前触发
   * @param {InjectCallback} [opt.afterOff] 取消注册事件后触发
   */
  setIntercept(opt) {
    if (!opt) return;
    Object.keys(opt).map(action => {
      this._hook.tap(action, opt[action]);
    });
  }

  /**
   * 绑定事件
   * @param {string} eventName 
   * @param {Function} callback 
   * @param {any} [options]
   */
  async on(eventName, callback, options) {
    if (baseUtil.isEmpty(eventName)) throw errUtil.pkgErr(EVENT_NAME_NULL);
    if (!baseUtil.isFun(callback)) throw errUtil.pkgErr(EVENT_CALLBACK_INVALID);
    if (this._sEvents && this._sEvents.indexOf(eventName) < 0) {
      throw errUtil.pkgErr(EVENT_UNSUPPORT, `${EVENT_UNSUPPORT.msg}: ${eventName}`);
    }

    await this._hook.callAsync('beforeOn', eventName, callback, options);
    this._eventer.on(eventName, callback);
    await this._hook.callAsync('afterOn', eventName, callback, options);
    return true;
  }

  /**
   * 解绑事件
   * @param {string} eventName 
   * @param {Function} callback 
   * @param {any} [options]
   */
  async off(eventName, callback, options, tp) {
    if (this.isClean(eventName, tp)) return true;

    await this._hook.callAsync('beforeOff', eventName, callback, options, tp);
    tp ? this._eventer.off('', callback, tp) : this._eventer.off(eventName, callback);
    await this._hook.callAsync('afterOff', eventName, callback, options, tp);
    return true;
  }

  /**
   * 事件覆盖
   * @param {string} eventName 
   * @param {Function} callback 
   * @param {any} [options]
   */
  async reset(eventName, callback, options) {
    await this.off(eventName);
    await this.on(eventName, callback, options);
    return true;
  }

  /**
   * 该事件下是否已没有注册监听
   * @param {*} eventName 
   */
  isClean(eventName, tp) {
    return this._eventer.isClean(eventName, tp);
  }

  /**
   * 事件触发
   * @param {Object} data 
   * @param {string} data.eventName 事件名
   * @param {any} data.params 事件内容
   */
  emit(data) {
    const { eventName, params } = this._hook.callWaterfall('resReducer', data) || data || {};
    if (!eventName) logger.warn(`eventName is null: ${JSON.stringify(data)}`);
    return this._eventer.emit(eventName, params);
  }

}