type EventCallback = (data?: any) => void

class CallbackAndContext {
  public callback: EventCallback = null
  public context: any = null

  public constructor(callback: EventCallback, context: any) {
    this.callback = callback
    this.context = context
  }
}

export class EventManager {
  private static instance: EventManager = null
  private listeners: { [eventName: string]: Array<CallbackAndContext> }

  public static Instance(): EventManager {
    if (!this.instance) {
      this.instance = new EventManager()
    }
    return this.instance
  }

  public On(eventName: string, callback: EventCallback, context?: any): void {
    if (!this.listeners[eventName]) {
      this.listeners[eventName] = []
    }
    if (!callback) return
    if (this.IsExsit(eventName, callback, context)) return
    this.listeners[eventName].push(new CallbackAndContext(callback, context))
  }

  private IsExsit(eventName: string, callback: EventCallback, context?: any): boolean {
    const listeners = this.listeners[eventName]
    if (!listeners) return false

    for (let i = listeners.length - 1; i >= 0; i--) {
      const listener = listeners[i]
      if (listener.callback === callback && (!context || listener.context === context)) {
        return true
      }
    }
    return false
  }

  // 取消事件监听
  public Off(eventName: string, callback?: EventCallback, context?: any): void {
    const listeners = this.listeners[eventName]
    if (!listeners) return
    // 如果没有提供回调，则移除该事件的所有监听
    if (!callback) {
      delete this.listeners[eventName]
      return
    }
    for (let i = listeners.length - 1; i >= 0; i--) {
      const listener = listeners[i]
      if (listener.callback === callback && (!context || listener.context === context)) {
        listeners.splice(i, 1)
      }
    }
    if (listeners.length === 0) {
      delete this.listeners[eventName]
    }
  }

  // 触发事件
  public Emit(eventName: string, data?: any): void {
    const listener = this.listeners[eventName]
    if (!listener) return
    // 创建副本，防止回调中修改原始数组
    const copy = [...listener]
    copy.forEach((listener) => {
      try {
        listener.callback.call(listener.context, data)
      } catch (error) {
        console.error(`事件回调错误,事件名: ${eventName}:`, error)
      }
    })
  }

  // 一次性监听（触发后自动移除）
  public Once(eventName: string, callback: EventCallback, context?: any): void {
    const wrapper = (data: any) => {
      callback.call(context, data)
      this.Off(eventName, wrapper, context)
    }
    this.On(eventName, wrapper, context)
  }

  // 移除所有事件监听
  public ClearAll(): void {
    this.listeners = {}
  }

  // 获取某个事件的监听者数量
  public ListenerCount(eventName: string): number {
    return this.listeners[eventName]?.length || 0
  }
}
