/*
 * @Description:
 * @Version: 1.0.0
 * @Autor: zenghaoming
 * @Date: 2023-04-21 14:10:04
 * @LastEditors: zenghaoming
 * @LastEditTime: 2023-11-06 17:48:45
 */
import { createId } from "./util/index";
import type {
  fnType,
  _EventObjType,
  _EventInterface,
  ConstructorProps,
  SubscribeReturn,
} from "./types";

export default class TwPublish<T> {
  private _event: _EventInterface<T>;
  //
  constructor(props: ConstructorProps<T[keyof T]>) {
    this._event = props.event || {}; // 做浅拷贝
  }
  // 事件的订阅
  public subscribe(name: keyof T, fn: fnType<T[keyof T]>): SubscribeReturn {
    const _name = name as string;
    //
    if (!this._event[_name]) {
      console.error(
        `${_name} 事件订阅失败，因为它不在事件 [` +
          Object.keys(this._event).join(",") +
          "] 范围内"
      );
      return { id: "", success: false };
    }
    if (!this._event[_name]) {
      this._event[_name] = [];
    }
    const id = createId();
    this._event[_name].push({ id, fn });
    return { id, success: true };
  }

  // 取消订阅
  public unsubscribe(name?: keyof T, id?: string) {
    const _name = name as string;
    if (!_name && !id) {
      // 都不传 则全部取消
      for (const key in this._event) {
        this._event[key] = [];
      }
      return;
    }
    // 传入名字
    if (_name && !id && this._event[_name]) {
      this._event[_name] = [];
      return;
    }
    // 都传入
    if (_name && id && this._event[_name]) {
      const arr = this._event[_name] || [];
      const index = arr.findIndex((item) => item.id === id);
      if (index !== -1) {
        arr.splice(index, 1);
      }
      return;
    }
  }

  // 事件的执行
  public publish(name: keyof T, data?: T[keyof T]) {
    const _name = name as string;
    if (!this._event[_name]) {
      console.error(
        `${_name} 事件发布失败，因为它不在事件 [` +
          Object.keys(this._event).join(",") +
          "] 范围内"
      );
      return;
    }
    const arr = this._event[_name] || [];
    arr.forEach((element: _EventObjType) => {
      element && element.fn && element.fn(data || null);
    });
  }
}
