import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
import { ref, computed, reactive, watch } from 'vue';
import { isUndefined, throttle, isPlainObject, isFunction } from 'lodash-es';
import getPrefixCls from '../_util/getPrefixCls';
import { getCellValue } from './helper';
import useTableLayout from './useTableLayout';

function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
const prefixCls = getPrefixCls('table');
var useTableStyle = _ref => {
  let {
    props,
    columns,
    columnsFixed,
    expandColumn,
    isExpandOpened,
    showData
  } = _ref;
  const wrapperRef = ref(null);
  const headerWrapperRef = ref(null);
  const bodyWrapperRef = ref(null);
  const scrollbarRef = ref(null);
  const bodyTableRef = ref(null);
  const isWidthAuto = computed(() => {
    return isUndefined(props.height) && props.layout === 'auto';
  });
  const wrapperClass = computed(() => [prefixCls, props.bordered && 'is-bordered', props.size && `is-size-${props.size}`, props.horizontalLine && 'is-horizontal-line', props.verticalLine && 'is-vertical-line'].filter(Boolean).join(' '));
  const layout = useTableLayout({
    wrapperRef,
    headerWrapperRef,
    bodyWrapperRef,
    bodyTableRef,
    props,
    columns,
    showData
  });
  const scrollState = reactive({
    x: '' // 默认为空值，避免左侧列固定的时候，右侧默认出现阴影区域
  });
  watch(computed(() => {
    var _scrollbarRef$value;
    return (_scrollbarRef$value = scrollbarRef.value) === null || _scrollbarRef$value === void 0 ? void 0 : _scrollbarRef$value.containerRef;
  }), () => {
    var _scrollbarRef$value2, _scrollbarRef$value3;
    // 有滚动条实例，说明实际内容宽度超出容器宽度，需要默认显示阴影区域
    if (!scrollState.x && (_scrollbarRef$value2 = scrollbarRef.value) !== null && _scrollbarRef$value2 !== void 0 && _scrollbarRef$value2.containerRef) {
      scrollState.x = 'left';
    } else if (scrollState.x && !((_scrollbarRef$value3 = scrollbarRef.value) !== null && _scrollbarRef$value3 !== void 0 && _scrollbarRef$value3.containerRef)) {
      scrollState.x = '';
    }
  });
  const headerWrapperClass = computed(() => {
    const arr = [`${prefixCls}-header-wrapper`];
    if (scrollState.x) {
      arr.push(`is-scrolling-x-${scrollState.x}`);
    }
    return arr;
  });

  /**
   * HeaderTable 不使用 Scrollbar
   * 因此需要处理 left, right, none 三种情况下的滚动内阴影
   * both 的情况由 cell 绘制阴影
   */
  const headerShadowVisible = computed(() => {
    if (columnsFixed.value === 'both') {
      return {
        left: false,
        right: false
      };
    }
    if (columnsFixed.value === 'none') {
      return {
        left: ['left', 'middle'].includes(scrollState.x),
        right: ['right', 'middle'].includes(scrollState.x)
      };
    }
    let left = false;
    let right = false;
    if (columnsFixed.value === 'left') {
      left = ['left', 'middle'].includes(scrollState.x);
    } else if (columnsFixed.value === 'right') {
      right = ['right', 'middle'].includes(scrollState.x);
    }
    return {
      left,
      right
    };
  });
  const bodyWrapperClass = computed(() => {
    const arr = [`${prefixCls}-body-wrapper`];
    if (scrollState.x) {
      arr.push(`is-scrolling-x-${scrollState.x}`);
    }
    /**
     * BodyTable 使用 Scrollbar
     * 仅处理单侧有固定列的情况
     * none 的情况由 Scrollbar 绘制阴影
     * both 的情况由 cell 绘制阴影
     */
    if (['left', 'right'].includes(columnsFixed.value)) {
      arr.push(`columns-fixed-${columnsFixed.value}`);
    }
    return arr;
  });
  const bodyWrapperStyle = computed(() => {
    const style = {};
    if (layout.isScrollY.value) {
      style.height = `${layout.bodyHeight.value}px`;
    }
    return style;
  });
  const headerStyle = computed(() => {
    if (isWidthAuto.value) {
      return {
        minWidth: '100%'
      };
    }
    const style = {
      width: `${layout.bodyWidth.value}px`
    };
    return style;
  });
  const bodyStyle = computed(() => {
    if (isWidthAuto.value) {
      return {
        minWidth: '100%'
      };
    }
    const style = {
      width: `${layout.bodyWidth.value}px`
    };
    return style;
  });
  const getRowClassName = _ref2 => {
    let {
      row,
      rowIndex
    } = _ref2;
    const classList = [`${prefixCls}-row`];
    const rowClassName = props.rowClassName;
    if (expandColumn.value) {
      classList.push(isExpandOpened({
        row
      }) && 'is-opened');
    }
    classList.push(typeof rowClassName === 'function' ? rowClassName({
      row,
      rowIndex
    }) : rowClassName);
    if (props.striped && rowIndex % 2 === 1) {
      classList.push('is-striped');
    }
    return classList.filter(Boolean);
  };
  const getRowStyle = _ref3 => {
    let {
      row,
      rowIndex
    } = _ref3;
    const rowStyle = props.rowStyle;
    if (isPlainObject(rowStyle)) {
      return rowStyle;
    }
    if (isFunction(rowStyle)) {
      return rowStyle({
        row,
        rowIndex
      });
    }
  };
  const getCellClass = _ref4 => {
    let {
      column,
      columns
    } = _ref4;
    const arr = [`${prefixCls}-cell`, column.id];
    // 兼容多级表头的情况
    const columnIndex = columns.findIndex(item => item.id === column.id);
    if (layout.isScrollX.value && column.fixedLeft) {
      var _columns;
      arr.push(`${prefixCls}-fixed-left`);
      if (!((_columns = columns[columnIndex + 1]) !== null && _columns !== void 0 && _columns.fixedLeft)) {
        arr.push('is-last');
      }
    }
    if (layout.isScrollX.value && column.fixedRight) {
      var _columns2;
      arr.push(`${prefixCls}-fixed-right`);
      if (!((_columns2 = columns[columnIndex - 1]) !== null && _columns2 !== void 0 && _columns2.fixedRight)) {
        arr.push('is-first');
      }
    }
    return arr;
  };
  const getCustomCellClass = _ref5 => {
    let {
      row,
      column,
      rowIndex,
      columnIndex
    } = _ref5;
    const colClassName = column.props.colClassName;
    const cellValue = getCellValue(row, column);
    return [typeof colClassName === 'function' ? colClassName({
      row,
      column,
      rowIndex,
      columnIndex,
      cellValue
    }) : colClassName];
  };
  const getCellStyle = _ref6 => {
    let {
      column,
      columns,
      row
    } = _ref6;
    // 兼容多级表头的情况
    const columnIndex = columns.findIndex(item => item.id === column.id);
    const align = column.props.align;
    const alignStyle = {
      'text-align': !row && column.colSpan > 1 ? 'center' : align
    };
    const fixedStyle = {};
    if (column.fixedLeft && layout.isScrollX.value) {
      const leftColumns = columns.slice(0, columnIndex);
      const width = leftColumns.reduce((accumulator, currentValue) => {
        var _layout$widthMap$valu, _layout$widthMap$valu2;
        const width = (_layout$widthMap$valu = layout.widthMap.value[currentValue.id]) === null || _layout$widthMap$valu === void 0 ? void 0 : _layout$widthMap$valu.width;
        const minWidth = (_layout$widthMap$valu2 = layout.widthMap.value[currentValue.id]) === null || _layout$widthMap$valu2 === void 0 ? void 0 : _layout$widthMap$valu2.minWidth;
        return (width || minWidth) + accumulator;
      }, 0);
      fixedStyle.left = `${width}px`;
    } else if (column.fixedRight && layout.isScrollX.value) {
      const rightColumns = columns.slice(columnIndex + 1);
      const width = rightColumns.reduceRight((accumulator, currentValue) => {
        var _layout$widthMap$valu3, _layout$widthMap$valu4;
        const width = (_layout$widthMap$valu3 = layout.widthMap.value[currentValue.id]) === null || _layout$widthMap$valu3 === void 0 ? void 0 : _layout$widthMap$valu3.width;
        const minWidth = (_layout$widthMap$valu4 = layout.widthMap.value[currentValue.id]) === null || _layout$widthMap$valu4 === void 0 ? void 0 : _layout$widthMap$valu4.minWidth;
        return (width || minWidth) + accumulator;
      }, 0);
      fixedStyle.right = `${width}px`;
    }
    return _objectSpread(_objectSpread({}, alignStyle), fixedStyle);
  };
  const getCustomCellStyle = _ref7 => {
    let {
      row,
      column,
      rowIndex,
      columnIndex
    } = _ref7;
    const cellValue = getCellValue(row, column);
    const colStyle = column.props.colStyle;
    let extraStyle = {};
    // row 为空，则是表头，表头不处理 colStyle
    if (row) {
      if (isPlainObject(colStyle)) {
        extraStyle = colStyle;
      }
      if (isFunction(colStyle)) {
        extraStyle = colStyle({
          row,
          column,
          rowIndex,
          columnIndex,
          cellValue
        });
      }
    }
    return extraStyle;
  };
  const getCellSpan = _ref8 => {
    let {
      row,
      column,
      rowIndex,
      columnIndex
    } = _ref8;
    let rowspan = '1';
    let colspan = '1';
    if (isFunction(props.spanMethod)) {
      const result = props.spanMethod({
        row,
        column,
        rowIndex,
        columnIndex
      });
      if (isPlainObject(result)) {
        rowspan = result.rowspan;
        colspan = result.colspan;
      }
    }
    return {
      rowspan,
      colspan
    };
  };

  // 更新 scrollState，根据 bodyWrapper 或 headerWrapper 的尺寸位置信息
  const updateScrollState = _ref9 => {
    let {
      scrollLeft,
      offsetWidth,
      scrollWidth
    } = _ref9;
    const maxScrollLeftPosition = scrollWidth - offsetWidth - 1;
    if (scrollLeft >= maxScrollLeftPosition) {
      scrollState.x = 'right';
    } else if (scrollLeft === 0) {
      scrollState.x = 'left';
    } else {
      scrollState.x = 'middle';
    }
  };

  // 边界场景：重置滚动状态
  watch([() => props.height, () => showData.value.length], (_ref10, _ref11) => {
    let [nextHeight, nextDataLength] = _ref10;
    let [prevHeight, prevDataLength] = _ref11;
    if (!props.showHeader) {
      return;
    }
    const resetScrolling = function () {
      let resetBodyTable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
      // BodyTable
      if (resetBodyTable && scrollbarRef.value && scrollbarRef.value.containerRef) {
        scrollbarRef.value.containerRef.scrollLeft = 0;
      }
      // HeaderTable
      if (headerWrapperRef.value) {
        headerWrapperRef.value.scrollLeft = 0;
      }
      // updateScrollState
      scrollState.x = 'left';
    };
    if (
    // <BodyTable> -> <NoData>
    prevDataLength !== 0 && nextDataLength === 0) {
      resetScrolling(false);
    } else if (
    // <NoData> -> <BodyTable>
    prevDataLength === 0 && nextDataLength !== 0) {
      resetScrolling();
    } else if (
    // 不固定表头 -> 固定表头
    isUndefined(prevHeight) && !isUndefined(nextHeight)) {
      resetScrolling();
    }
  });

  // BodyTable 滚动后，同步 HeaderTable(可能不存在) 的 scrollLeft
  const syncPosition = throttle(e => {
    const $bodyWrapper = e.target;
    if (!$bodyWrapper) {
      return;
    }
    const {
      scrollLeft,
      offsetWidth,
      scrollWidth
    } = $bodyWrapper;
    const $headerWrapper = headerWrapperRef.value;
    if ($headerWrapper) {
      $headerWrapper.scrollLeft = scrollLeft;
    }
    updateScrollState({
      scrollLeft,
      offsetWidth,
      scrollWidth
    });
  }, 10);
  const handleHeaderMousewheel = e => {
    const {
      deltaX,
      deltaY
    } = e;
    if (Math.abs(deltaX) >= Math.abs(deltaY)) {
      e.preventDefault();

      /**
       * 没有数据时，
       * bodyWrapper 的 offsetWidth === scrollWidth，此时设置 scrollLeft 不生效
       * 无法通过 bodyWrapper 的 scroll 事件回调触发 syncPosition 以更新 headerWrapper 的 scrollLeft
       * 注意，headerWrapper 的 overflow 为 hidden，可以响应 scroll 事件但是元素无法滚动
       */
      if (showData.value.length === 0 && headerWrapperRef.value) {
        headerWrapperRef.value.scrollLeft += deltaX;
        const {
          scrollLeft,
          offsetWidth,
          scrollWidth
        } = headerWrapperRef.value;
        updateScrollState({
          scrollLeft,
          offsetWidth,
          scrollWidth
        });
        return;
      }

      /**
       * 有数据时，
       * 仍按照原逻辑，先更新 bodyWrapper 的 scrollLeft，再 syncPosition
       */
      if (scrollbarRef.value && scrollbarRef.value.containerRef) {
        scrollbarRef.value.containerRef.scrollLeft += deltaX;
      }
    }
  };
  return {
    prefixCls,
    wrapperRef,
    headerWrapperRef,
    bodyWrapperRef,
    layout,
    wrapperClass,
    bodyWrapperStyle,
    headerStyle,
    bodyStyle,
    getCellSpan,
    getRowClassName,
    getRowStyle,
    getCellClass,
    getCustomCellClass,
    getCellStyle,
    getCustomCellStyle,
    syncPosition,
    headerShadowVisible,
    handleHeaderMousewheel,
    headerWrapperClass,
    bodyWrapperClass,
    scrollbarRef,
    bodyTableRef
  };
};

export { useTableStyle as default };
