import _slicedToArray from "@babel/runtime-corejs3/helpers/slicedToArray";
import _extends from "@babel/runtime-corejs3/helpers/extends";
import _toConsumableArray from "@babel/runtime-corejs3/helpers/toConsumableArray";
import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter";
import { makeRecursiveMapper, mergeCellProps, collectNodes, isLeafNode } from '../../utils';
import { FILL_COLUMN_CODE } from './autoFill';
var stateKey = 'columnDrag';
var SCROLL_SIZE = 30;

function disableSelect(event) {
  event.preventDefault();
}

function sortColumns(columns, sort) {
  var res = new Array(columns.length);

  var lastColumns = _toConsumableArray(columns);

  while (columns.length) {
    var cloumn = columns.pop();
    res[sort[cloumn.code]] = cloumn;
  }

  if (_filterInstanceProperty(res).call(res, Boolean).length !== lastColumns.length) {
    return lastColumns;
  }

  return res;
}

function stopClickPropagation(e) {
  e.stopPropagation();
}

export function columnDrag() {
  var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  return function (pipeline) {
    var _pipeline$getStateAtK = pipeline.getStateAtKey(stateKey, {}),
        cloumnsTranslateData = _pipeline$getStateAtK.cloumnsTranslateData;

    var columns = pipeline.getColumns();
    var tableBody = pipeline.ref.current.domHelper && pipeline.ref.current.domHelper.tableBody; // if (cloumnsSortData) {
    //   columns = sortColumns(columns, cloumnsSortData)
    // }

    pipeline.columns(_filterInstanceProperty(columns).call(columns, function (column) {
      return column;
    }));
    return pipeline.mapColumns(makeRecursiveMapper(function (col, recursiveFlatMapInfo) {
      var path = recursiveFlatMapInfo.path,
          isLeaf = recursiveFlatMapInfo.isLeaf;
      var style = cloumnsTranslateData ? {
        transition: '.3s',
        transform: "translate3d(".concat(cloumnsTranslateData[col.code], "px, 0px, 0px)")
      } : {};
      var prevGetCellProps = col.getCellProps; // !col.code: 选择列 col.lock: 固定列 不允许拖拽

      if (col.lock || !col.code) return col;
      return _extends(_extends({}, col), {
        getCellProps: function getCellProps(value, record, rowIndex) {
          var prevCellProps = prevGetCellProps === null || prevGetCellProps === void 0 ? void 0 : prevGetCellProps(value, record, rowIndex);
          return mergeCellProps(prevCellProps, {
            style: style
          });
        },
        headerCellProps: mergeCellProps(col.headerCellProps, {
          onMouseDown: !isLeaf || path.length > 1 ? undefined : function (e) {
            if (e.button !== 0) {
              return;
            }

            window.addEventListener('selectstart', disableSelect); // const cx = e.clientX
            // const width = col.width
            // const a = startIndex
            // const b = endIndex
            // const newColumnDragData = [...columnDragData]
            // let newColumn = [...columns]
            // let newStartIndex = startIndex
            // let endIdx = endIndex

            var columnMoved = false;
            var columns = pipeline.getColumns();

            var _pipeline$getStateAtK2 = pipeline.getStateAtKey(stateKey, {}),
                cloumnsTranslateData = _pipeline$getStateAtK2.cloumnsTranslateData;

            var cloumnsSortData = {};
            columns.forEach(function (item, index) {
              cloumnsSortData[item.code] = index;
            });
            var currentTarget = e.currentTarget;
            var rect = e.currentTarget.parentElement.getClientRects()[0];
            var startX = rect.left;
            var moveData = [];
            var allColumns = collectNodes(columns);
            var tableBodyClientRect = tableBody.getBoundingClientRect();
            var startScrollLeft = pipeline.ref.current.domHelper.virtual.scrollLeft;

            var updateScrollPosition = function updateScrollPosition(client) {
              var clientX = client.clientX;
              var left = tableBodyClientRect.left,
                  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;
              }
            };

            var stopClickPropagationFlag = false;

            function handleMouseMove(e) {
              var client = {
                clientX: e.clientX,
                clientY: e.clientY
              };
              var scrollDistance = pipeline.ref.current.domHelper.virtual.scrollLeft - startScrollLeft;
              var leftPosition = startX - scrollDistance; // 表头最左边起点

              updateScrollPosition(client);

              if (e.clientX - leftPosition < 20) {
                return;
              } else {
                // 阻止列头点击事件，防止拖动后触发列头过滤事件
                if (stopClickPropagationFlag === false) {
                  stopClickPropagationFlag = true;
                  currentTarget.addEventListener('click', stopClickPropagation);
                }

                e.stopPropagation();
              }

              document.body.style.userSelect = 'none';
              currentTarget.style.cursor = 'move'; // 循环计算每一个的位置
              // if (startIndex !== replaceIndex) {
              //   const optionColumn = columns[startIndex]
              //   const move = startIndex > replaceIndex ? 1 : -1
              //   let index = Math.min(startIndex, replaceIndex)
              //   while (index < Math.max(startIndex, replaceIndex)) {
              //     const code = columns[index].code
              //     cloumnsTranslateData[code] += move * optionColumn.width
              //     cloumnsTranslateData[optionColumn.code] -= move * optionColumn.width
              //     index += move
              //   }
              // }
              // const opColumn = columns[startIndex]
              // let index = Math.min(startIndex, replaceIndex)
              // while (index <= Math.max(startIndex, replaceIndex)) {
              //   const code = columns[index].code
              //   if (index !== startIndex && index !== replaceIndex) {
              //     cloumnsTranslateData[code] += opColumn.width * (index > startIndex ? -1 : 1)
              //     cloumnsTranslateData[opColumn.code] += columns[index].width * (index < startIndex ? -1 : 1)
              //   }
              //   index++
              // }
              // 重置位置信息

              cloumnsTranslateData = {};
              allColumns.forEach(function (item) {
                cloumnsTranslateData[item.code] = 0;
              }); // 计算平移位置

              var replaceIndex = 0;
              var totalWitdth = getColumnWidth(columns[replaceIndex]);

              while (totalWitdth < e.clientX - leftPosition && replaceIndex < columns.length - 1) {
                replaceIndex++;
                totalWitdth += getColumnWidth(columns[replaceIndex]);
              } // 需要取最新startIndex, 不能直接用makeRecursiveMapper提供的startIndex（因为map时还没添加选择列、充满列等后面use添加的列）


              var startIndex;
              columns.forEach(function (column, index) {
                if (column.code === col.code) {
                  startIndex = index;
                }
              });
              var optionColumn = columns[startIndex];
              var index = replaceIndex;

              if (startIndex > replaceIndex) {
                // 左移
                while (index < startIndex) {
                  var _columns$index = columns[index],
                      code = _columns$index.code,
                      lock = _columns$index.lock,
                      width = _columns$index.width,
                      children = _columns$index.children;

                  if (enableMove({
                    code: code,
                    lock: lock
                  })) {
                    cloumnsTranslateData[code] += optionColumn.width;

                    if (isLeafNode(columns[index])) {
                      cloumnsTranslateData[optionColumn.code] -= width;
                    } else {
                      cloumnsTranslateData[optionColumn.code] -= getColumnWidth(columns[index]);
                      moveAllChildren(children, cloumnsTranslateData, optionColumn.width);
                    }

                    columnMoved = true;
                  }

                  index++;
                }
              } else if (startIndex < replaceIndex) {
                // 右移
                while (startIndex < index) {
                  var _columns$index2 = columns[index],
                      _code = _columns$index2.code,
                      _lock = _columns$index2.lock,
                      _width = _columns$index2.width,
                      _children = _columns$index2.children;

                  if (enableMove({
                    code: _code,
                    lock: _lock
                  })) {
                    cloumnsTranslateData[_code] -= optionColumn.width;

                    if (isLeafNode(columns[index])) {
                      cloumnsTranslateData[optionColumn.code] += _width;
                    } else {
                      cloumnsTranslateData[optionColumn.code] += getColumnWidth(columns[index]);
                      moveAllChildren(_children, cloumnsTranslateData, optionColumn.width, true);
                    }

                    columnMoved = true;
                  }

                  index--;
                }
              }

              window.requestAnimationFrame(function () {
                pipeline.setStateAtKey(stateKey, {
                  cloumnsTranslateData: cloumnsTranslateData
                });
                moveData = [startIndex, replaceIndex];
              });
            }

            function handleMouseUp(e) {
              e.stopPropagation();
              document.body.removeEventListener('mousemove', handleMouseMove);
              document.body.removeEventListener('mouseup', handleMouseUp);
              window.removeEventListener('selectstart', disableSelect);
              window.requestAnimationFrame(function () {
                // 取消阻止列头点击事件
                currentTarget.removeEventListener('click', stopClickPropagation);
                stopClickPropagationFlag = false;
                currentTarget = null;

                var _moveData = moveData,
                    _moveData2 = _slicedToArray(_moveData, 2),
                    startIndex = _moveData2[0],
                    replaceIndex = _moveData2[1];

                var optionColumn = columns[startIndex]; // const move = startIndex > replaceIndex ? 1 : -1
                // let index = Math.min(startIndex, replaceIndex)
                // while (index < Math.max(startIndex, replaceIndex) && index > 0) {
                //   const code = columns[index].code
                //   cloumnsSortData[optionColumn.code] -= move
                //   cloumnsSortData[code] += move
                //   index += move
                // }

                var index = replaceIndex;

                if (startIndex > replaceIndex) {
                  // 左移
                  while (index < startIndex) {
                    var _columns$index3 = columns[index],
                        code = _columns$index3.code,
                        lock = _columns$index3.lock;

                    if (enableMove({
                      code: code,
                      lock: lock
                    })) {
                      cloumnsSortData[code] += 1;
                      cloumnsSortData[optionColumn.code] -= 1;
                      columnMoved = true;
                    }

                    index++;
                  }
                } else if (startIndex < replaceIndex) {
                  // 右移
                  while (index > startIndex) {
                    var _columns$index4 = columns[index],
                        _code2 = _columns$index4.code,
                        _lock2 = _columns$index4.lock;

                    if (enableMove({
                      code: _code2,
                      lock: _lock2
                    })) {
                      cloumnsSortData[_code2] -= 1;
                      cloumnsSortData[optionColumn.code] += 1;
                      columnMoved = true;
                    }

                    index--;
                  }
                }

                var onColumnDragStopped = opts.onColumnDragStopped; // 拖拽结束返回列顺序

                if (onColumnDragStopped) {
                  var _context;

                  var newColumns = _filterInstanceProperty(_context = sortColumns(columns, cloumnsSortData)).call(_context, function (_ref) {
                    var code = _ref.code;
                    return code !== FILL_COLUMN_CODE;
                  }); // TODO drag需要在resize之后use,否则这里返回的列对应的宽度不是拖拽后的


                  onColumnDragStopped(columnMoved, newColumns);
                }

                pipeline.setStateAtKey(stateKey, {
                  cloumnsTranslateData: null
                });
              });
              document.body.style.userSelect = '';
              currentTarget.style.opacity = '';
              currentTarget.style.cursor = '';
            }

            document.body.addEventListener('mousemove', handleMouseMove);
            document.body.addEventListener('mouseup', handleMouseUp);
          },
          style: style
        })
      });
    }));
  };
}

function enableMove(_ref2) {
  var lock = _ref2.lock,
      code = _ref2.code;
  return code && code !== FILL_COLUMN_CODE && !lock;
}

function getColumnWidth(col) {
  if (col.children) {
    return col.children.reduce(function (acc, col) {
      return acc + getColumnWidth(col);
    }, 0);
  }

  return col.width;
}

function moveAllChildren(cols, cloumnsTranslateData, width, isMinus) {
  cols.forEach(function (col) {
    var _a;

    var code = col.code,
        children = col.children;
    var movedWidth = (_a = cloumnsTranslateData[code]) !== null && _a !== void 0 ? _a : 0;
    cloumnsTranslateData[code] = movedWidth + (isMinus ? -width : width);

    if (!isLeafNode(col)) {
      moveAllChildren(children, cloumnsTranslateData, width);
    }
  });
}