import XEUtils from 'xe-utils';
import UtilTools from '../../tools/utils';
import DomTools from '../../tools/dom';
import { convertToRows } from './util';
import { getColReMinWidth } from '../../table/src/util';

const cellType = 'header';

export default {
  name: 'TablePlusHeader',
  props: {
    tableData: Array,
    tableColumn: Array,
    tableGroupColumn: Array,
    fixedColumn: Array,
    size: String,
    fixedType: String
  },
  data() {
    return {
      headerColumn: []
    };
  },
  watch: {
    tableColumn() {
      this.uploadColumn();
    }
  },
  created() {
    this.uploadColumn();
  },
  mounted() {
    const { $parent: $tablePlus, $el, $refs, fixedType } = this;
    const { elemStore } = $tablePlus;
    const prefix = `${fixedType || 'main'}-header-`;
    elemStore[`${prefix}wrapper`] = $el;
    elemStore[`${prefix}table`] = $refs.table;
    elemStore[`${prefix}colgroup`] = $refs.colgroup;
    elemStore[`${prefix}list`] = $refs.thead;
    elemStore[`${prefix}xSpace`] = $refs.xSpace;
    elemStore[`${prefix}repair`] = $refs.repair;
  },
  destroyed() {
    const { $parent: $tablePlus, fixedType } = this;
    const { elemStore } = $tablePlus;
    const prefix = `${fixedType || 'main'}-header-`;
    elemStore[`${prefix}wrapper`] = null;
    elemStore[`${prefix}table`] = null;
    elemStore[`${prefix}colgroup`] = null;
    elemStore[`${prefix}list`] = null;
    elemStore[`${prefix}xSpace`] = null;
    elemStore[`${prefix}repair`] = null;
  },
  render(h) {
    const {
      _e,
      $parent: $tablePlus,
      fixedType,
      headerColumn,
      tableColumn,
      fixedColumn
    } = this;
    const {
      $listeners: tableListeners,
      tId,
      isGroup,
      visibleColumn,
      resizable,
      border,
      columnKey,
      headerRowClassName,
      headerCellClassName,
      headerRowStyle,
      headerCellStyle,
      showHeaderOverflow: allColumnHeaderOverflow,
      headerAlign: allHeaderAlign,
      align: allAlign,
      highlightCurrentColumn,
      currentColumn,
      scrollXLoad,
      overflowX,
      scrollbarWidth,
      sortOpts,
      mouseConfig,
      columnOpts
    } = $tablePlus;
    let headerGroups = headerColumn;
    let renderColumnList = tableColumn;
    if (isGroup) {
      renderColumnList = visibleColumn;
    } else {
      // 如果是使用优化模式
      if (fixedType) {
        if (scrollXLoad || allColumnHeaderOverflow) {
          renderColumnList = fixedColumn;
        }
      }
      headerGroups = [renderColumnList];
    }
    return h(
      'div',
      {
        class: [
          'el-table-plus--header-wrapper el-table__header-wrapper',
          fixedType ? `fixed-${fixedType}--wrapper` : 'body--wrapper'
        ],
        attrs: {
          xid: tId
        }
      },
      [
        fixedType
          ? _e()
          : h('div', {
            class: 'table-plus-body--x-space',
            ref: 'xSpace'
          }),
        h(
          'table',
          {
            class: 'el-table-plus--header el-table__header',
            attrs: {
              xid: tId,
              cellspacing: 0,
              cellpadding: 0,
              border: 0
            },
            ref: 'table'
          },
          [
            /**
             * 列宽
             */
            h(
              'colgroup',
              {
                ref: 'colgroup'
              },
              renderColumnList
                .map((column, $columnIndex) => {
                  return h('col', {
                    attrs: {
                      name: column.id
                    },
                    key: $columnIndex
                  });
                })
                .concat(
                  scrollbarWidth
                    ? [
                      h('col', {
                        attrs: {
                          name: 'col_gutter'
                        }
                      })
                    ]
                    : []
                )
            ),
            /**
             * 头部
             */
            h(
              'thead',
              {
                ref: 'thead'
              },
              headerGroups.map((cols, $rowIndex) => {
                return h(
                  'tr',
                  {
                    class: [
                      'table-plus-header--row',
                      headerRowClassName
                        ? XEUtils.isFunction(headerRowClassName)
                          ? headerRowClassName({
                            $table: $tablePlus,
                            $rowIndex,
                            fixed: fixedType,
                            type: cellType
                          })
                          : headerRowClassName
                        : ''
                    ],
                    style: headerRowStyle
                      ? XEUtils.isFunction(headerRowStyle)
                        ? headerRowStyle({
                          $table: $tablePlus,
                          $rowIndex,
                          fixed: fixedType,
                          type: cellType
                        })
                        : headerRowStyle
                      : null
                  },
                  cols
                    .map((column, $columnIndex) => {
                      const {
                        type,
                        showHeaderOverflow,
                        headerAlign,
                        align,
                        headerClassName
                      } = column;
                      // const { enabled } = tooltipOpts
                      const isColGroup =
                        column.children && column.children.length;
                      const fixedHiddenColumn = fixedType
                        ? column.fixed !== fixedType && !isColGroup
                        : column.fixed && overflowX;
                      const headOverflow =
                        XEUtils.isUndefined(showHeaderOverflow) ||
                        XEUtils.isNull(showHeaderOverflow)
                          ? allColumnHeaderOverflow
                          : showHeaderOverflow;
                      const headAlign =
                        headerAlign || align || allHeaderAlign || allAlign;
                      let showEllipsis = headOverflow === 'ellipsis';
                      const showTitle = headOverflow === 'title';
                      const showTooltip =
                        headOverflow === true || headOverflow === 'tooltip';
                      let hasEllipsis = showTitle || showTooltip || showEllipsis;
                      const thOns = {};
                      const hasFilter =
                        column.filters &&
                        column.filters.some((item) => item.checked);
                      const columnIndex = $tablePlus.getColumnIndex(column);
                      const _columnIndex = $tablePlus.getVTColumnIndex(column);
                      const params = {
                        $table: $tablePlus,
                        $grid: $tablePlus.xegrid,
                        $rowIndex,
                        column,
                        columnIndex,
                        $columnIndex,
                        _columnIndex,
                        fixed: fixedType,
                        type: cellType,
                        isHidden: fixedHiddenColumn,
                        hasFilter
                      };
                      // 虚拟滚动不支持动态高度
                      if (scrollXLoad && !hasEllipsis) {
                        showEllipsis = hasEllipsis = true;
                      }
                      if (
                        columnOpts.isCurrent ||
                        highlightCurrentColumn ||
                        tableListeners['header-cell-click'] ||
                        sortOpts.trigger === 'cell'
                      ) {
                        thOns.click = (evnt) =>
                          $tablePlus.triggerHeaderCellClickEvent(evnt, params);
                      }
                      if (tableListeners['header-cell-dblclick']) {
                        thOns.dblclick = (evnt) =>
                          $tablePlus.triggerHeaderCellDblclickEvent(evnt, params);
                      }
                      // 按下事件处理
                      if (mouseConfig) {
                        thOns.mousedown = (evnt) =>
                          $tablePlus.triggerHeaderCellMousedownEvent(evnt, params);
                      }
                      return h(
                        'th',
                        {
                          class: [
                            'table-plus-header--column el-table__cell',
                            column.id,
                            {
                              [`col--${headAlign}`]: headAlign,
                              [`col--${type}`]: type,
                              'col--last': $columnIndex === cols.length - 1,
                              'col--fixed': column.fixed,
                              'col--group': isColGroup,
                              'col--ellipsis': hasEllipsis,
                              'fixed--hidden': fixedHiddenColumn,
                              'is--sortable': column.sortable,
                              'col--filter': !!column.filters,
                              'is--filter-active': hasFilter,
                              'col--current': currentColumn === column
                            },
                            UtilTools.getClass(headerClassName, params),
                            UtilTools.getClass(headerCellClassName, params)
                          ],
                          attrs: {
                            colid: column.id,
                            colspan: column.colSpan > 1 ? column.colSpan : null,
                            rowspan: column.rowSpan > 1 ? column.rowSpan : null
                          },
                          style: headerCellStyle
                            ? XEUtils.isFunction(headerCellStyle)
                              ? headerCellStyle(params)
                              : headerCellStyle
                            : null,
                          on: thOns,
                          key:
                            columnKey || columnOpts.useKey || isColGroup
                              ? column.id
                              : $columnIndex
                        },
                        [
                          h(
                            'div',
                            {
                              class: [
                                'table-plus-cell cell',
                                {
                                  'c--title': showTitle,
                                  'c--tooltip': showTooltip,
                                  'c--ellipsis': showEllipsis
                                }
                              ]
                            },
                            column.renderHeader(h, params)
                          ),
                          /**
                           * 列宽拖动
                           */
                          !fixedHiddenColumn &&
                          !isColGroup &&
                          (XEUtils.isBoolean(column.resizable)
                            ? column.resizable
                            : columnOpts.resizable || resizable)
                            ? h('div', {
                              class: [
                                'table-plus-resizable',
                                {
                                  'is--line': !border || border === 'none'
                                }
                              ],
                              on: {
                                mousedown: (evnt) =>
                                  this.resizeMousedown(evnt, params)
                              }
                            })
                            : null
                        ]
                      );
                    })
                    .concat(
                      scrollbarWidth
                        ? [
                          h('th', {
                            class:
                                'table-plus-header--gutter col--gutter el-table__cell gutter'
                          })
                        ]
                        : []
                    )
                );
              })
            )
          ]
        ),
        /**
         * 其他
         */
        h('div', {
          class: 'el-table-plus--header-border-line',
          ref: 'repair'
        })
      ]
    );
  },
  methods: {
    uploadColumn() {
      const { $parent: $tablePlus } = this;
      this.headerColumn = $tablePlus.isGroup
        ? convertToRows(this.tableGroupColumn)
        : [];
    },
    resizeMousedown(evnt, params) {
      const { column } = params;
      const { $parent: $tablePlus, $el, fixedType } = this;
      const {
        tableBody,
        leftContainer,
        rightContainer,
        resizeBar: resizeBarElem
      } = $tablePlus.$refs;
      const { target: dragBtnElem, clientX: dragClientX } = evnt;
      const cell = (params.cell = dragBtnElem.parentNode);
      let dragLeft = 0;
      const tableBodyElem = tableBody.$el;
      const pos = DomTools.getOffsetPos(dragBtnElem, $el);
      const dragBtnWidth = dragBtnElem.clientWidth;
      const dragBtnOffsetWidth = Math.floor(dragBtnWidth / 2);
      const minInterval = getColReMinWidth(params) - dragBtnOffsetWidth; // 列之间的最小间距
      let dragMinLeft = pos.left - cell.clientWidth + dragBtnWidth + minInterval;
      let dragPosLeft = pos.left + dragBtnOffsetWidth;
      const domMousemove = document.onmousemove;
      const domMouseup = document.onmouseup;
      const isLeftFixed = fixedType === 'left';
      const isRightFixed = fixedType === 'right';

      // 计算左右侧固定列偏移量
      let fixedOffsetWidth = 0;
      if (isLeftFixed || isRightFixed) {
        const siblingProp = isLeftFixed
          ? 'nextElementSibling'
          : 'previousElementSibling';
        let tempCellElem = cell[siblingProp];
        while (tempCellElem) {
          if (DomTools.hasClass(tempCellElem, 'fixed--hidden')) {
            break;
          } else if (!DomTools.hasClass(tempCellElem, 'col--group')) {
            fixedOffsetWidth += tempCellElem.offsetWidth;
          }
          tempCellElem = tempCellElem[siblingProp];
        }
        if (isRightFixed && rightContainer) {
          dragPosLeft = rightContainer.offsetLeft + fixedOffsetWidth;
        }
      }

      // 处理拖动事件
      const updateEvent = function(evnt) {
        evnt.stopPropagation();
        evnt.preventDefault();
        const offsetX = evnt.clientX - dragClientX;
        let left = dragPosLeft + offsetX;
        const scrollLeft = fixedType ? 0 : tableBodyElem.scrollLeft;
        if (isLeftFixed) {
          // 左固定列（不允许超过右侧固定列、不允许超过右边距）
          left = Math.min(
            left,
            (rightContainer
              ? rightContainer.offsetLeft
              : tableBodyElem.clientWidth) -
              fixedOffsetWidth -
              minInterval
          );
        } else if (isRightFixed) {
          // 右侧固定列（不允许超过左侧固定列、不允许超过左边距）
          dragMinLeft =
            (leftContainer ? leftContainer.clientWidth : 0) +
            fixedOffsetWidth +
            minInterval;
          left = Math.min(left, dragPosLeft + cell.clientWidth - minInterval);
        } else {
          dragMinLeft = Math.max(tableBodyElem.scrollLeft, dragMinLeft);
          // left = Math.min(left, tableBodyElem.clientWidth + tableBodyElem.scrollLeft - 40)
        }
        dragLeft = Math.max(left, dragMinLeft);
        resizeBarElem.style.left = `${dragLeft - scrollLeft}px`;
      };

      $tablePlus._isResize = true;
      DomTools.addClass($tablePlus.$el, 'drag--resize');
      resizeBarElem.style.display = 'block';
      document.onmousemove = updateEvent;
      document.onmouseup = function(evnt) {
        document.onmousemove = domMousemove;
        document.onmouseup = domMouseup;
        const resizeWidth =
          column.renderWidth +
          (isRightFixed ? dragPosLeft - dragLeft : dragLeft - dragPosLeft);
        column.resizeWidth = resizeWidth;
        resizeBarElem.style.display = 'none';
        $tablePlus._isResize = false;
        $tablePlus._lastResizeTime = Date.now();
        $tablePlus.analyColumnWidth();
        $tablePlus.recalculate(true).then(() => {
          $tablePlus.saveCustomResizable();
          $tablePlus.updateCellAreas();
          $tablePlus.emitEvent(
            'resizable-change',
            { ...params, resizeWidth },
            evnt
          );
        });
        DomTools.removeClass($tablePlus.$el, 'drag--resize');
      };
      updateEvent(evnt);
      $tablePlus.closeMenu();
    }
  }
};
