import { getCurrentInstance, ref, h } from 'vue'
import { getStyle, hasClass } from '@element-plus/utils/dom'
import { createTablePopper, getCell, getColumnByCell } from '../util'
import debounce from 'lodash/debounce'
import { TableColumnCtx } from '../table-column/defaults'
import { Table } from '../table/defaults'
import { TableBodyProps } from './defaults'

function useEvents<T>(props: Partial<TableBodyProps<T>>) {
  const instance = getCurrentInstance()
  const parent = instance.parent as Table<T>
  const tooltipContent = ref('')
  const tooltipTrigger = ref(h('div'))
  const handleEvent = (event: Event, row: T, name: string) => {
    const table = parent
    const cell = getCell(event)
    let column: TableColumnCtx<T>
    if (cell) {
      column = getColumnByCell(
        {
          columns: props.store.states.columns.value,
        },
        cell,
      )
      if (column) {
        table.emit(`cell-${name}`, row, column, cell, event)
      }
    }
    table.emit(`row-${name}`, row, column, event)
  }
  const handleDoubleClick = (event: Event, row: T) => {
    handleEvent(event, row, 'dblclick')
  }
  const handleClick = (event: Event, row: T) => {
    props.store.commit('setCurrentRow', row)
    handleEvent(event, row, 'click')
  }
  const handleContextMenu = (event: Event, row: T) => {
    handleEvent(event, row, 'contextmenu')
  }
  const handleMouseEnter = debounce(function(index: number) {
    props.store.commit('setHoverRow', index)
  }, 30)
  const handleMouseLeave = debounce(function() {
    props.store.commit('setHoverRow', null)
  }, 30)
  const handleCellMouseEnter = (
    event: MouseEvent,
    row: T & { tooltipEffect: string; },
  ) => {
    const table = parent
    const cell = getCell(event)

    if (cell) {
      const column = getColumnByCell(
        {
          columns: props.store.states.columns.value,
        },
        cell,
      )
      const hoverState = (table.hoverState = { cell, column, row })
      table.emit(
        'cell-mouse-enter',
        hoverState.row,
        hoverState.column,
        hoverState.cell,
        event,
      )
    }

    // 判断是否text-overflow, 如果是就显示tooltip
    const cellChild = (event.target as HTMLElement).querySelector(
      '.cell',
    ) as HTMLElement
    if (!(hasClass(cellChild, 'el-tooltip') && cellChild.childNodes.length)) {
      return
    }
    // use range width instead of scrollWidth to determine whether the text is overflowing
    // to address a potential FireFox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1074543#c3
    const range = document.createRange()
    range.setStart(cellChild, 0)
    range.setEnd(cellChild, cellChild.childNodes.length)
    const rangeWidth = range.getBoundingClientRect().width
    const padding =
      (parseInt(getStyle(cellChild, 'paddingLeft'), 10) || 0) +
      (parseInt(getStyle(cellChild, 'paddingRight'), 10) || 0)
    if (
      rangeWidth + padding > cellChild.offsetWidth ||
      cellChild.scrollWidth > cellChild.offsetWidth
    ) {
      createTablePopper(
        cell,
        cell.innerText || cell.textContent,
        {
          placement: 'top',
          strategy: 'fixed',
        },
        row.tooltipEffect,
      )
    }
  }
  const handleCellMouseLeave = event => {
    const cell = getCell(event)
    if (!cell) return

    const oldHoverState = parent.hoverState
    parent.emit(
      'cell-mouse-leave',
      oldHoverState?.row,
      oldHoverState?.column,
      oldHoverState?.cell,
      event,
    )
  }

  return {
    handleDoubleClick,
    handleClick,
    handleContextMenu,
    handleMouseEnter,
    handleMouseLeave,
    handleCellMouseEnter,
    handleCellMouseLeave,
    tooltipContent,
    tooltipTrigger,
  }
}

export default useEvents
