import { v4 } from 'uuid'
import { EventKey, EventBus } from './types'

/**
 * 事件总线
 */
export default new (class {
    private events = new Map<string, EventBus>()

    /** 监听事件 */
    $on(eventKey: EventKey | EventKey[], callback: EventBus['callback'], once = false) {
        const uuid = v4()
        const keys = Array.isArray(eventKey) ? eventKey : [eventKey]

        this.events.set(uuid, {
            keys,
            once,
            callback
        })

        /** 销毁事件，注意离开页面时要手动销毁当前页面订阅的事件，防止事件重复触发 */
        return {
            uuid,
            cancel: () => this.events.delete(uuid)
        }
    }

    /** 触发事件 */
    $emit(eventKey: EventKey, ...data: unknown[]) {
        for (const [uuid, e] of this.events.entries()) {
            if (e.keys.includes(eventKey)) {
                e.callback(...data)
                e.once && this.events.delete(uuid)
            }
        }
    }

    /** 取消事件 */
    $off(...eventKeys: EventKey[]) {  
        const keySet = new Set(eventKeys)
        const uuidsToDelete = new Set<string>()
        
        for (const [uuid, e] of this.events) {
          // 使用 filter 方法来创建一个新的 keys 数组，只包含未被取消的事件键
          const remainingKeys = e.keys.filter(key => !keySet.has(key))
          if (remainingKeys.length === 0) {
            // 如果没有剩余的事件键，则添加 UUID 到删除集合中
            uuidsToDelete.add(uuid)
          } else if (remainingKeys.length !== e.keys.length) {
            // 如果事件键被部分取消，则更新事件的 keys 数组
            this.events.set(uuid, { ...e, keys: remainingKeys })
          }
        }
        
        // 在遍历完成后，删除需要删除的事件
        for (const uuid of uuidsToDelete) {  
          this.events.delete(uuid)
        }
      }
})