import _typeof from "@babel/runtime-corejs3/helpers/typeof";
import _defineProperty from "@babel/runtime-corejs3/helpers/defineProperty";
import _extends from "@babel/runtime-corejs3/helpers/extends";
import _findIndexInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/find-index";
import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice";
import { mergeCellProps, makeRecursiveMapper, isElementInEventPath, collectNodes } from '../../utils';
import { findByTree } from '../../utils/others';
import { fromEvent } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { Classes } from '../../base/styles';
import cx from 'classnames';
export var rangeSelectionKey = 'rangeSelection';
export var lastClickCell = 'lastClickCell';
export function rangeSelection(opts) {
  return function step(pipeline) {
    var SCROLL_SIZE = 30;
    var tableBody = pipeline.ref.current.domHelper && pipeline.ref.current.domHelper.tableBody;

    if (!tableBody) {
      return pipeline;
    }

    var columns = pipeline.getColumns();

    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);
    }; // if (!pipeline.getFeatureOptions(rangeSelectionKey)) {
    //   pipeline.setFeatureOptions(rangeSelectionKey, {
    //     optionKey: rangeSelectionKey,
    //     rangeSelectedChange: rangeSelectedChange
    //   })
    // }


    var setRangeSelection = function setRangeSelection(startDragCell, draggingCell) {
      if (!startDragCell || !draggingCell || isSameCell(startDragCell, draggingCell)) return;
      var rangeColumns = getRangeColumns(startDragCell, draggingCell, columns);
      var isTopToBottom = startDragCell.rowIndex <= draggingCell.rowIndex;
      var rangeSelection = {
        startRow: isTopToBottom ? startDragCell.rowIndex : startDragCell.rowIndex + startDragCell.rowSpan - 1,
        endRow: isTopToBottom ? draggingCell.rowIndex + draggingCell.rowSpan - 1 : draggingCell.rowIndex,
        columns: rangeColumns,
        startColumn: startDragCell.column
      };
      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(lastClickCell);

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

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

      shiftKeySelect(mouseDownEvent);
      var target = mouseDownEvent.target;
      var startDragCell = getTargetCell(target, columns);
      var mousemove$ = fromEvent(window, 'mousemove');
      var mouseup$ = 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(map(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
        };
      }), takeUntil(mouseup$));
      rangeSelected$.subscribe(function (_ref) {
        var startDragCell = _ref.startDragCell,
            draggingCell = _ref.draggingCell;
        setRangeSelection(startDragCell, draggingCell);
      });
    };

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

      if ((e.ctrlKey || e.metaKey) && e.key === 'a') {
        var rowLen = pipeline.getDataSource().length;

        if (columns.length && rowLen) {
          opts.preventkDefaultOfKeyDownEvent !== false && e.preventDefault();
          rangeSelectedChange({
            startRow: 0,
            endRow: rowLen - 1,
            columns: columns,
            startColumn: columns[0]
          });
        }
      }
    };

    pipeline.addTableProps({
      onMouseDown: onMouseDown,
      onKeyDown: onKeyDown,
      tabIndex: -1
    }); // todo: 后面可以把mousedown放到一个流里面

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

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

          var prevCellProps = prevGetCellProps === null || prevGetCellProps === void 0 ? void 0 : prevGetCellProps(value, record, rowIndex);
          var startRow = rangeSelection.startRow,
              endRow = rangeSelection.endRow,
              columns = rangeSelection.columns;
          var startIndex = startRow < endRow ? startRow : endRow;
          var endIndex = startRow < endRow ? endRow : startRow;
          var startCol = columns[0];
          var endCol = columns[columns.length - 1];
          var match = rowIndex >= startIndex && rowIndex <= endIndex;
          var className = cx((_cx = {}, _defineProperty(_cx, Classes.tableCellRangeSelected, match), _defineProperty(_cx, Classes.tableCellRangeTop, rowIndex === startIndex), _defineProperty(_cx, Classes.tableCellRangeLeft, col.code === startCol.code && match), _defineProperty(_cx, Classes.tableCellRangeBottom, rowIndex === endIndex), _defineProperty(_cx, Classes.tableCellRangeRight, col.code === endCol.code && match), _cx));
          return 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 = 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
          }
        };
      }();

      if (_typeof(_ret) === "object") return _ret.v;
    }

    target = target.parentElement;
  }

  return null;
}

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

function getRangeColumns(startCell, endCell, columns) {
  var flatColumns = collectNodes(columns, 'leaf-only');

  var startIndex = _findIndexInstanceProperty(flatColumns).call(flatColumns, function (col) {
    return col.code === startCell.code;
  });

  var endIndex = _findIndexInstanceProperty(flatColumns).call(flatColumns, function (col) {
    return col.code === endCell.code;
  });

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