import { MonitorElement } from '.'
import { localLog } from './utils'

const listenersWeakMap = new WeakMap<HTMLElement, Set<string>>()

const add = (el: HTMLElement, action: string, handler: EventListener) => {
  if (!listenersWeakMap.has(el)) {
    listenersWeakMap.set(el, new Set())
  }

  if (listenersWeakMap.get(el)?.has(action)) return

  listenersWeakMap.get(el)?.add(action)

  el.addEventListener(action, handler, false)
}

const remove = (el: MonitorElement, action?: string) => {
  const listeners = listenersWeakMap.get(el) || new Set()
  if (action) {
    listeners.delete(action)
    el.removeEventListener(action, handler)
  } else {
    listeners.forEach((action) => el.removeEventListener(action, handler))
    listenersWeakMap.delete(el)
  }
}

export const monitorElement = (el: MonitorElement) => {
  const actions = el.__monitor_actions || []
  actions.forEach((action) => {
    add(el, action, handler)
  })
}

export const unmonitorElement = (el: MonitorElement) => {
  ;(el.__monitor_actions || []).forEach((action) => {
    remove(el, action)
  })
}

function handler(event: Event) {
  try {
    const { type } = event
    const currentTarget = event.currentTarget as MonitorElement
    const params = JSON.parse(currentTarget?.dataset?.monitor || '{}')[type]
    const extra = JSON.parse(currentTarget?.dataset?.monitorExtra || '{}')
    const data = { ...params, params: { ...(params.params || {}), ...extra } }
    if (!currentTarget.__monitor?.request) {
      localLog(data)
    }
    currentTarget.__monitor?.request(data)
  } catch (e) {
    console.error(e)
  }
}
