<script lang="tsx">
import {
  computed, defineComponent, ref, type PropType,
} from 'vue'
import { type paramsSerializationOptions } from '../../../composables/use-endless-scroll-api'
import { getTextWidth } from '../../../helpers'
import type ApiInterface from '../../../types/api-interface'
import Tooltip from '../../tooltips/BlackTooltip.vue'
import { type ComputedColumnInterface } from '../DefaultTableInterfaces'
import { type FilterData } from '../filters/Filters'
import {
  isCalendarHeaderInterface,
  isDefaultSelectHeaderInterface,
  isEnumSelectHeaderInterface,
  isMultipleDefaultSelectHeaderInterface,
  isMultipleEnumSelectHeaderInterface,
  isMultipleParamsRelationSelectHeaderInterface,
  isMultipleRelationSelectHeaderInterface,
  isNumberSearchHeaderInterface,
  isPeriodCalendarHeaderInterface,
  isRangeNumberHeaderInterface,
  isRelationSelectHeaderInterface,
  isTextHeaderInterface,
  isTextSearchHeaderInterface,
} from './HeadersTableInterfaces'
import CalendarHeader from './headers/DefaultTableHeaderCalendar.vue'
import DefaultSelectHeader from './headers/DefaultTableHeaderDefaultSelect.vue'
import EmptyHeader from './headers/DefaultTableHeaderEmpty.vue'
import EnumSelectHeader from './headers/DefaultTableHeaderEnumSelect.vue'
import NumberSearchHeader from './headers/DefaultTableHeaderNumberSearch.vue'
import PeriodCalendarHeader from './headers/DefaultTableHeaderPeriodCalendar.vue'
import RangeNumberHeader from './headers/DefaultTableHeaderRangeNumber.vue'
import RelationSelectHeader from './headers/DefaultTableHeaderRelationSelect.vue'
import TextHeader from './headers/DefaultTableHeaderText.vue'
import TextSearchHeader from './headers/DefaultTableHeaderTextSearch.vue'
import MultipleDefaultSelectHeader from './headers/multiple/DefaultTableHeaderDefaultSelectMultiple.vue'
import MultipleEnumSelectHeader from './headers/multiple/DefaultTableHeaderEnumSelectMultiple.vue'
import MultipleRelationSelectHeader from './headers/multiple/DefaultTableHeaderRelationSelectMultiple.vue'
import type { ResizableInterface } from '../composables/useResizableColumns'

export default defineComponent({
  props: {
    api: {
      type: Object as PropType<ApiInterface>,
      default: undefined,
    },
    canResizeColumns: {
      type: Boolean,
      default: true,
    },
    column: {
      type: Object as PropType<ComputedColumnInterface>,
      required: true,
    },
    columnIndex: {
      type: Number,
      required: true,
    },
    enableSorting: {
      type: Boolean,
    },
    horizontalEyesightMargins: {
      type: Array as PropType<number[]>,
      default: () => [],
    },
    params: {
      type: Array as PropType<FilterData[]>,
      default: undefined,
    },
    paramsSerialization: {
      type: String as PropType<paramsSerializationOptions>,
      default: 'default',
    },
    resizedColumn: {
      type: Object as PropType<ResizableInterface | undefined>,
      default: undefined,
    },
    visualOffset: {
      type: Number,
      default: 0,
    },
    setSort: {
      type: Function as PropType<(column: ComputedColumnInterface) => void>,
      required: true,
    },
    smartFilter: {
      type: Boolean,
      default: false,
    },
    sortField: {
      type: String,
      required: true,
    },
    sortOrder: {
      type: Boolean,
    },
    isResizing: {
      type: Boolean,
      default: false,
    },
    tableContainer: {
      type: [Object, null] as PropType<HTMLElement | null>,
      default: null,
    },
    resizerHeight: {
      type: Number,
      default: 0,
    },
  },

  emits: [
    'startResize', 'stopResize',
    'mouseEnter', 'mouseLeave',
  ],

  setup(props, { emit }) {
    const headerCellRef = ref<HTMLElement | null>(null)
    const headerIconsAndPaddingWidth = props.column.header.type === 'text' ? 49 : 95
    const styles = computed(() => `
      width: ${props.column.width}px;
      min-width: ${props.column.width}px;
      max-width: ${props.column.width}px;
      pointer-events: ${props.isResizing ? 'none' : ''};
      --horizontalEyesightMargin: ${props.horizontalEyesightMargins[props.columnIndex] || 0}px;
    `)

    const resizerStyles = computed(() => ({
      transform: `translateX(${props.visualOffset}px)`,
      height: props.resizerHeight ? `${props.resizerHeight}px` : '100vh',
    }))

    const handleMouseDown = (e: MouseEvent) => {
      emit('startResize', e, headerCellRef.value, props.tableContainer)
    }

    const renderHeader = (column: ComputedColumnInterface) => {
      const smartFilter = Boolean(typeof column.header.smartFilter === 'boolean' ? column.header.smartFilter : props.smartFilter)

      type HeaderProps = {
        api?: ApiInterface
        sortField: string
        sortOrder?: boolean
        column: ComputedColumnInterface
        onSort?: () => void
        params?: FilterData[]
        paramsSerialization: paramsSerializationOptions
        enableSorting?: boolean
      }

      const headerProps: HeaderProps = {
        api: props.api,
        column,
        sortField: props.sortField,
        sortOrder: props.sortOrder,
        onSort: column.sort ? () => props.setSort(column) : undefined,
        params: smartFilter ? props.params : [],
        paramsSerialization: props.paramsSerialization,
        enableSorting: props.enableSorting,
      }

      if (isTextHeaderInterface(column.header)) return <TextHeader {...headerProps} />
      if (isTextSearchHeaderInterface(column.header)) return <TextSearchHeader {...headerProps} />
      if (isNumberSearchHeaderInterface(column.header)) return <NumberSearchHeader {...headerProps} />
      if (isRangeNumberHeaderInterface(column.header)) return <RangeNumberHeader {...headerProps} />

      if (isCalendarHeaderInterface(column.header)) return <CalendarHeader {...headerProps} />
      if (isPeriodCalendarHeaderInterface(column.header)) return <PeriodCalendarHeader {...headerProps} />

      if (isRelationSelectHeaderInterface(column.header)) return <RelationSelectHeader {...headerProps} />
      if (isMultipleRelationSelectHeaderInterface(column.header)) return <MultipleRelationSelectHeader {...headerProps} />
      if (isMultipleParamsRelationSelectHeaderInterface(column.header)) return <RelationSelectHeader {...headerProps} />

      if (isEnumSelectHeaderInterface(column.header)) return <EnumSelectHeader {...headerProps} />
      if (isMultipleEnumSelectHeaderInterface(column.header)) return <MultipleEnumSelectHeader {...headerProps} />

      if (isDefaultSelectHeaderInterface(column.header)) return <DefaultSelectHeader {...headerProps} />
      if (isMultipleDefaultSelectHeaderInterface(column.header)) return <MultipleDefaultSelectHeader {...headerProps} />

      return <EmptyHeader/>
    }

    return () => (
      <div
        ref={headerCellRef}
        class={`ark-ui-table-header-cell ${props.column.horizontalEyesight ? 'ark-ui-table-eyesight' : ''}`}
        style={styles.value}
      >
        {(props.column.width - headerIconsAndPaddingWidth) <= getTextWidth(props.column.headerTooltipText || props.column.name, '500 14px Roboto') ? (
          <Tooltip
            text={props.column.headerTooltipText || props.column.name || ''}
            class='ark-ui-table-header-cell-tooltip'
            positionCorrectingY={24}
            positionCorrectingX={16}
          >
            {renderHeader(props.column)}
          </Tooltip>
        ) : renderHeader(props.column)}

        {props.canResizeColumns && !props.column.horizontalEyesight && (
          <div
            class={`ark-ui-table-call-resizer ark-ui-table-call-resizer-after ${props.column.isResizing ? 'active' : ''}`}
            style={resizerStyles.value}
          >
            <div class={`ark-ui-table-call-resizer-item ${props.column.isResizing ? 'active' : ''}`}/>

            <div
              class="ark-ui-table-call-resizer-draggable"
              onMousedown={handleMouseDown}
              onMouseenter={() => emit('mouseEnter')}
              onMouseleave={() => emit('mouseLeave')}
            />
          </div>
        )}
      </div>
    )
  },
})
</script>
