"use strict";

var _mapInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/map");

var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.lastClickCellKey = void 0;
exports.rangeSelection = rangeSelection;
exports.rangeSelectionKey = void 0;

var _typeof2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/typeof"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));

var _extends2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/extends"));

var _findIndex = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/find-index"));

var _slice = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/slice"));

var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));

var _utils = require("../../utils");

var _others = require("../../utils/others");

var _rxjs = require("rxjs");

var _operators = require("rxjs/operators");

var _styles = require("../../base/styles");

var _classnames = _interopRequireDefault(require("classnames"));

var rangeSelectionKey = 'rangeSelection';
exports.rangeSelectionKey = rangeSelectionKey;
var lastClickCellKey = 'lastClickCell';
exports.lastClickCellKey = lastClickCellKey;

function rangeSelection(opts) {
  return function step(pipeline) {
    var SCROLL_SIZE = 30;
    var tableBody = pipeline.ref.current.domHelper && pipeline.ref.current.domHelper.tableBody;
    var tableFooter = pipeline.ref.current.domHelper && pipeline.ref.current.domHelper.tableFooter;

    if (!tableBody) {
      return pipeline;
    }

    var columns = pipeline.getColumns();
    var dataSource = pipeline.getDataSource();

    var rangeSelectedChange = function rangeSelectedChange(rangeSelection) {
      var _a;

      pipeline.setStateAtKey(rangeSelectionKey, rangeSelection);
      (_a = opts === null || opts === void 0 ? void 0 : opts.rangeSelectedChange) === null || _a === void 0 ? void 0 : _a.call(opts, rangeSelection);
    };

    var setRangeSelection = function setRangeSelection(startDragCell, draggingCell) {
      if (!startDragCell || !draggingCell) return;
      var rangeColumns = getRangeColumns(startDragCell, draggingCell, columns);

      var _getRangeSelectionRow = getRangeSelectionRowInfo(startDragCell, draggingCell, dataSource),
          startRow = _getRangeSelectionRow.startRow,
          endRow = _getRangeSelectionRow.endRow,
          footerRowRange = _getRangeSelectionRow.footerRowRange;

      var rangeSelection = {
        startRow: startRow,
        endRow: endRow,
        columns: rangeColumns,
        startColumn: startDragCell.column,
        footerRowRange: footerRowRange
      };
      rangeSelectedChange(rangeSelection);
    };

    var shiftKeySelect = function shiftKeySelect(event) {
      var target = event.target;
      var clickCell = getTargetCell(target, columns);

      if (clickCell) {
        if (event.shiftKey) {
          var _lastClickCell = pipeline.getStateAtKey(lastClickCellKey);

          if (_lastClickCell) {
            setRangeSelection(_lastClickCell, clickCell);
          } else {
            // 第一次进来就按住shift键，这时候要记住点击的单元格
            pipeline.setStateAtKey(lastClickCellKey, clickCell);
          }
        } else {
          pipeline.setStateAtKey(lastClickCellKey, clickCell);
          setRangeSelection(clickCell, clickCell);
        }
      }
    };

    var onMouseDown = function onMouseDown(mouseDownEvent) {
      if (mouseDownEvent.button !== 0 || !((0, _utils.isElementInEventPath)(tableBody, mouseDownEvent.nativeEvent) || (0, _utils.isElementInEventPath)(tableFooter, mouseDownEvent.nativeEvent))) return; // mouseDownEvent.preventDefault()
      // shift + 点击选中

      shiftKeySelect(mouseDownEvent);
      var target = mouseDownEvent.target;
      var startDragCell = getTargetCell(target, columns);
      var mousemove$ = (0, _rxjs.fromEvent)(window, 'mousemove');
      var mouseup$ = (0, _rxjs.fromEvent)(window, 'mouseup');
      var tableBodyClientRect = tableBody.getBoundingClientRect();

      var updateScrollPosition = function updateScrollPosition(client) {
        var clientX = client.clientX,
            clientY = client.clientY;
        var left = tableBodyClientRect.left,
            top = tableBodyClientRect.top,
            height = tableBodyClientRect.height,
            width = tableBodyClientRect.width;

        if (clientX + SCROLL_SIZE >= left + width) {
          pipeline.ref.current.domHelper.virtual.scrollLeft += SCROLL_SIZE;
        }

        if (clientX - SCROLL_SIZE <= left) {
          pipeline.ref.current.domHelper.virtual.scrollLeft -= SCROLL_SIZE;
        }

        if (clientY + SCROLL_SIZE >= top + height) {
          pipeline.ref.current.domHelper.tableBody.scrollTop += SCROLL_SIZE;
        }

        if (clientY + SCROLL_SIZE <= top) {
          pipeline.ref.current.domHelper.tableBody.scrollTop -= SCROLL_SIZE;
        }
      };

      var rangeSelected$ = mousemove$.pipe((0, _mapInstanceProperty(_operators))(function (mouseMoveEvent) {
        var target = mouseMoveEvent.target || mouseMoveEvent.srcElement;
        var draggingCell = getTargetCell(target, columns);
        var client = {
          clientX: mouseMoveEvent.clientX,
          clientY: mouseMoveEvent.clientY
        };
        updateScrollPosition(client);
        return {
          startDragCell: startDragCell,
          draggingCell: draggingCell
        };
      }), (0, _operators.takeUntil)(mouseup$));
      rangeSelected$.subscribe(function (_ref) {
        var startDragCell = _ref.startDragCell,
            draggingCell = _ref.draggingCell;
        setRangeSelection(startDragCell, draggingCell);
      });
    };

    var onKeyDown = function onKeyDown(e) {
      if (!((0, _utils.isElementInEventPath)(tableBody, e.nativeEvent) || (0, _utils.isElementInEventPath)(tableFooter, e.nativeEvent))) return;

      if ((e.ctrlKey || e.metaKey) && e.key === 'a') {
        var rowLen = pipeline.getDataSource().length;
        var footerDataSource = pipeline.getFooterDataSource() || []; // 焦点位于可编辑的单元格内不做全选

        if (columns.length && rowLen && !getElementEditable(e.target)) {
          opts.preventkDefaultOfKeyDownEvent !== false && e.preventDefault();
          rangeSelectedChange({
            startRow: 0,
            endRow: rowLen - 1,
            columns: (0, _utils.collectNodes)(columns, 'leaf-only'),
            startColumn: columns[0],
            footerRowRange: footerDataSource.length > 0 ? {
              startRow: 0,
              endRow: footerDataSource.length - 1
            } : null
          });
        }
      }
    };

    pipeline.addTableProps({
      onMouseDown: onMouseDown,
      onKeyDown: onKeyDown,
      tabIndex: -1,
      className: (0, _classnames.default)([_styles.Classes.rangeSelection])
    }); // todo: 后面可以把mousedown放到一个流里面

    return pipeline.mapColumns((0, _utils.makeRecursiveMapper)(function (col) {
      var _context;

      var rangeSelection = pipeline.getStateAtKey(rangeSelectionKey);
      if (!rangeSelection || (0, _findIndex.default)(_context = rangeSelection.columns).call(_context, function (selectedCol) {
        return selectedCol.code === col.code;
      }) === -1) return col;
      var prevGetCellProps = col.getCellProps;
      return (0, _extends2.default)((0, _extends2.default)({}, col), {
        getCellProps: function getCellProps(value, record, rowIndex) {
          var _cx;

          var prevCellProps = prevGetCellProps === null || prevGetCellProps === void 0 ? void 0 : prevGetCellProps(value, record, rowIndex);
          var isInFooter = record[pipeline.getFeatureOptions('footerRowMetaKey')];
          var startRow = rangeSelection.startRow,
              endRow = rangeSelection.endRow,
              columns = rangeSelection.columns,
              footerRowRange = rangeSelection.footerRowRange;

          var _getRowIndex = getRowIndex(startRow, endRow),
              startRowIndex = _getRowIndex.startRowIndex,
              endRowIndex = _getRowIndex.endRowIndex;

          var _getFooterRowIndex = getFooterRowIndex(footerRowRange),
              footerStartRowIndex = _getFooterRowIndex.startRowIndex,
              footerEndRowIndex = _getFooterRowIndex.endRowIndex;

          var startCol = columns[0];
          var endCol = columns[columns.length - 1];
          var bodyMatch = !isInFooter && rowIndex >= startRowIndex && rowIndex <= endRowIndex;
          var footerMatch = isInFooter && footerRowRange && rowIndex >= footerStartRowIndex && rowIndex <= footerEndRowIndex;
          var match = footerMatch || bodyMatch;
          var matchSingleCell = match && isCellRangeSingleCell(rangeSelection); // 单个范围选中单元格不显示样式

          var showCellRangeStyle = match && !matchSingleCell;
          var className = (0, _classnames.default)((_cx = {}, (0, _defineProperty2.default)(_cx, _styles.Classes.tableCellRangeSingleCell, matchSingleCell), (0, _defineProperty2.default)(_cx, _styles.Classes.tableCellRangeSelected, showCellRangeStyle), (0, _defineProperty2.default)(_cx, _styles.Classes.tableCellRangeTop, showCellRangeStyle && (isInFooter ? startRowIndex !== -1 ? false : rowIndex === footerStartRowIndex : rowIndex === startRowIndex)), (0, _defineProperty2.default)(_cx, _styles.Classes.tableCellRangeLeft, showCellRangeStyle && col.code === startCol.code), (0, _defineProperty2.default)(_cx, _styles.Classes.tableCellRangeBottom, showCellRangeStyle && (isInFooter ? rowIndex === footerEndRowIndex : footerRowRange ? false : rowIndex === endRowIndex)), (0, _defineProperty2.default)(_cx, _styles.Classes.tableCellRangeRight, showCellRangeStyle && col.code === endCol.code), _cx));
          return (0, _utils.mergeCellProps)(prevCellProps, {
            className: className
          });
        }
      });
    }));
  };
}

function getTargetCell(target, columns) {
  while (target) {
    if (target.getAttribute('data-role') === 'table-cell') {
      var _ret = function () {
        var columnCode = target.getAttribute('data-code');
        var column = (0, _others.findByTree)(columns, function (item, index) {
          return item.code === columnCode;
        });
        if (!column) return {
          v: null
        };
        return {
          v: {
            rowIndex: parseInt(target.getAttribute('data-rowindex')),
            rowSpan: parseInt(target.getAttribute('rowspan') || 1),
            code: columnCode,
            column: column,
            isInFooter: isEleInFooter(target)
          }
        };
      }();

      if ((0, _typeof2.default)(_ret) === "object") return _ret.v;
    }

    target = target.parentElement;
  }

  return null;
}

function isSameCell(cell1, cell2) {
  return cell1.rowIndex === cell2.rowIndex && cell1.code === cell2.code && cell1.isInFooter === cell2.isInFooter;
}

function isEleInFooter(target) {
  while (target && !target.classList.contains(_styles.Classes.artTable)) {
    if (target.classList.contains(_styles.Classes.tableFooter)) {
      return true;
    }

    target = target.parentElement;
  }

  return false;
}

function getRangeColumns(startCell, endCell, columns) {
  var flatColumns = (0, _utils.collectNodes)(columns, 'leaf-only');
  var startIndex = (0, _findIndex.default)(flatColumns).call(flatColumns, function (col) {
    return col.code === startCell.code;
  });
  var endIndex = (0, _findIndex.default)(flatColumns).call(flatColumns, function (col) {
    return col.code === endCell.code;
  });

  if (startIndex < endIndex) {
    return (0, _slice.default)(flatColumns).call(flatColumns, startIndex, endIndex + 1);
  } else {
    return (0, _slice.default)(flatColumns).call(flatColumns, endIndex, startIndex + 1);
  }
}

function getRangeSelectionRowInfo(startCell, endCell, dataSource) {
  var footerRowRange = null;
  var startRow = -1;
  var endRow = -1;

  var _getCellRangeRow = getCellRangeRow(startCell, endCell),
      _startRow = _getCellRangeRow.startRow,
      _endRow = _getCellRangeRow.endRow; // 两个单元格都在表体


  if (!startCell.isInFooter && !endCell.isInFooter) {
    startRow = _startRow;
    endRow = _endRow;
  } else if (startCell.isInFooter && endCell.isInFooter) {
    // 两个单元格都在表底
    footerRowRange = {
      startRow: _startRow,
      endRow: _endRow
    };
  } else {
    // 一个单元格在表体，一个在表底
    if (startCell.isInFooter) {
      startRow = dataSource.length - 1;
      endRow = endCell.rowIndex;
      footerRowRange = {
        startRow: startCell.rowIndex,
        endRow: 0
      };
    } else {
      startRow = startCell.rowIndex;
      endRow = dataSource.length - 1;
      footerRowRange = {
        startRow: 0,
        endRow: endCell.rowIndex
      };
    }
  }

  return {
    startRow: startRow,
    endRow: endRow,
    footerRowRange: footerRowRange
  };
}

function getCellRangeRow(startCell, endCell) {
  if (isSameCell(startCell, endCell)) {
    return {
      startRow: startCell.rowIndex,
      endRow: startCell.rowIndex
    };
  }

  var isTopToBottom = startCell.rowIndex <= endCell.rowIndex;
  var startRow = isTopToBottom ? startCell.rowIndex : startCell.rowIndex + startCell.rowSpan - 1;
  var endRow = isTopToBottom ? endCell.rowIndex + endCell.rowSpan - 1 : endCell.rowIndex;
  return {
    startRow: startRow,
    endRow: endRow
  };
}

function isCellRangeSingleCell(rangeSelection) {
  var startRow = rangeSelection.startRow,
      endRow = rangeSelection.endRow,
      columns = rangeSelection.columns,
      footerRowRange = rangeSelection.footerRowRange;
  var isBodySingleCell = !footerRowRange && startRow === endRow && columns.length === 1;
  var isFooterSingleCell = startRow === -1 && footerRowRange.startRow === footerRowRange.endRow && columns.length === 1;
  return isBodySingleCell || isFooterSingleCell;
}

function getRowIndex(startRow, endRow) {
  var isReverse = startRow > endRow;
  var startRowIndex = isReverse ? endRow : startRow;
  var endRowIndex = isReverse ? startRow : endRow;
  return {
    startRowIndex: startRowIndex,
    endRowIndex: endRowIndex
  };
}

function getFooterRowIndex(footerRowRange) {
  if (footerRowRange) {
    return getRowIndex(footerRowRange.startRow, footerRowRange.endRow);
  }

  return {
    startRowIndex: -1,
    endRowIndex: -1
  };
}

function getElementEditable(target) {
  var _context2;

  if (!target) return;

  if ((0, _includes.default)(_context2 = ['input', 'textarea']).call(_context2, target.tagName.toLowerCase())) {
    if (target.type === 'checkbox') return;
    return !target.disabled && !target.readOnly;
  }
}