/**
 * --------------------------------------------------------------------------
 * Bootstrap util/component-functions.ts
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 * --------------------------------------------------------------------------
 */

import type BaseComponent from '../base-component.js'
import EventHandler, { type BootstrapEvent } from '../dom/event-handler.js'
import SelectorEngine from '../dom/selector-engine.js'
import { isDisabled } from './index.js'

interface EventActionData {
  targets: HTMLElement[]
  event: BootstrapEvent
}

const enableDismissTrigger = (component: typeof BaseComponent, method = 'hide'): void => {
  const clickEvent = `click.dismiss${component.EVENT_KEY}`
  const name = component.NAME

  EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) {
    if (['A', 'AREA'].includes(this.tagName)) {
      event.preventDefault()
    }

    if (isDisabled(this)) {
      return
    }

    // Responsive variants replace the base class with a breakpoint-prefixed one, such
    // as `lg:drawer`, which `.${name}` cannot match
    const target = SelectorEngine.getElementFromSelector(this) ||
      this.closest(`.${name}, [class*=":${name}"]`)
    const instance: any = component.getOrCreateInstance(target)

    // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method
    instance[method]()
  })
}

type EventActionCallback = (data: EventActionData & { instances: BaseComponent[] }) => void

const eventActionOnPlugin = (Plugin: typeof BaseComponent, onEvent: string, stringSelector: string, method: string, callback: EventActionCallback | null = null): void => {
  eventAction(`${onEvent}.${Plugin.NAME}`, stringSelector, data => {
    const instances = data.targets.filter(Boolean).map(element => Plugin.getOrCreateInstance(element))
    if (typeof callback === 'function') {
      callback({ ...data, instances })
    }

    for (const instance of instances) {
      (instance as any)[method]()
    }
  })
}

const eventAction = (onEvent: string, stringSelector: string, callback: (data: EventActionData) => void): void => {
  const selector = `${stringSelector}:not(.disabled):not(:disabled)`
  EventHandler.on(document, onEvent, selector, function (event) {
    if (['A', 'AREA'].includes(this.tagName)) {
      event.preventDefault()
    }

    const selector = SelectorEngine.getSelectorFromElement(this)
    const targets = selector ? SelectorEngine.find(selector) : [this as HTMLElement]

    callback({ targets, event })
  })
}

export {
  enableDismissTrigger,
  eventActionOnPlugin
}
