import { LitElement, nothing } from 'lit'
import { customElement, queryAsync } from 'lit/decorators.js'
import { EventEmitterMixin } from '../EventEmitterMixin'
import { WrappingMixin } from '../WrappingMixin'

@customElement('btu-table')
export default class Table extends EventEmitterMixin(
  WrappingMixin(LitElement),
) {
  @queryAsync('table') _table!: Promise<HTMLTableElement>

  connectedCallback(): void {
    super.connectedCallback()

    this._table.then((table) => {
      const checkAll = table.querySelector<HTMLInputElement>(
        ':scope th > input[type="checkbox"]',
      )

      checkAll?.addEventListener('click', this._updateCheckAll)

      table
        .querySelectorAll<HTMLInputElement>(
          ':scope > tbody input[type="checkbox"]',
        )
        .forEach((c) => {
          c.addEventListener('click', this._updateSelectAll)
        })
    })
  }

  disconnectedCallback() {
    super.disconnectedCallback()

    this._table.then((table) => {
      const checkAll = table.querySelector<HTMLInputElement>(
        ':scope th > input[type="checkbox"]',
      )

      checkAll?.removeEventListener('click', this._updateCheckAll)

      table
        .querySelectorAll<HTMLInputElement>(
          ':scope > tbody input[type="checkbox"]',
        )
        .forEach((c) => {
          c.removeEventListener('click', this._updateSelectAll)
        })
    })
  }

  createRenderRoot() {
    return this
  }

  // When all checkboxes are checked, the check all checkbox should be checked.
  private _updateSelectAll = (e: Event) => {
    this._table.then((table) => {
      const checkAll = table.querySelector<HTMLInputElement>(
        ':scope th > input[type="checkbox"]',
      )
      const checkboxes = table.querySelectorAll<HTMLInputElement>(
        ':scope > tbody input[type="checkbox"]',
      )

      const checkedItems = table.querySelectorAll<HTMLInputElement>(
        ':scope > tbody input[type="checkbox"]:checked',
      )

      if (checkAll) {
        checkAll.checked =
          checkboxes.length > 0 && checkedItems.length === checkboxes.length

        this.emit('btu-table-checked-all')
      }
    })
  }

  // When check all checkbox is checked, check every other checkboxes.
  private _updateCheckAll = (e: Event) => {
    this._table.then((table) => {
      const checkAll = e.target

      if (checkAll instanceof HTMLInputElement) {
        table
          .querySelectorAll<HTMLInputElement>(
            ':scope > tbody input[type="checkbox"]',
          )
          .forEach((c) => {
            c.checked = checkAll.checked
          })

        this.emit('btu-table-checked-all')
      }
    })
  }

  render() {
    return nothing
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'btu-table': Table
  }
}
