type ObjectKey = string | number | symbol
type AnyFunction = (...args: any[]) => any
 
class EventBus {
  // Map<eventName, Map<originalCallback, callback>>
  // originalCallback 用于取消 once 注册的回调
  private events: Map<ObjectKey, Map<AnyFunction, AnyFunction>>
 
  constructor() {
    this.events = new Map()
  }
 
  // 使用泛型的原因:...args 有类型,方便代码提示和类型检查
  emit<T extends AnyFunction>(eventName: ObjectKey, ...args: Parameters<T>) {
    const events = this.events.get(eventName)
    if (!events) {
      return
    }
    events.forEach(callback => {
      callback(...args)
    })
  }
 
  on<T extends AnyFunction>(eventName: ObjectKey, callback: T) {
    this._on(eventName, callback, callback)
  }
 
  once<T extends AnyFunction>(eventName: ObjectKey, callback: T) {
    // 包装方法:执行一次后取消订阅
    const wrapper = (...args: Parameters<T>) => {
      callback(...args)
      this.off(eventName, callback)
    }
    this._on(eventName, wrapper, callback)
  }
 
  off<T extends AnyFunction>(eventName: ObjectKey, callback: T): boolean {
    const events = this.events.get(eventName)
    if (!events) {
      return false
    }
    return events.delete(callback)
  }
 
  offAll(eventName: ObjectKey): boolean {
    return this.events.delete(eventName)
  }
 
  private _on(eventName: ObjectKey, callback: AnyFunction, originalCallback: AnyFunction) {
    let events = this.events.get(eventName)
    if (!events) {
      events = new Map()
      this.events.set(eventName, events)
    }
    events.set(originalCallback, callback)
  }
}