/**
 * ldesign v0.4.2
 * (c) 2023 ldesign
 * @license MIT
 */

import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
import _createClass from '@babel/runtime/helpers/createClass';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import isUndefined from 'lodash/isUndefined';
import get from 'lodash/get';
import '../log/index.js';
import { isRowSelectedDisabled } from './utils.js';
import log from '../log/log.js';
import 'lodash/isFunction';
import 'lodash/isNumber';

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
var TABLE_TREE_ERROR_CODE_NOT_SAME_LEVEL = {
  code: 1001,
  reason: "The same level of rows can not be swapped."
};
var TableTreeStore = /*#__PURE__*/function () {
  function TableTreeStore() {
    _classCallCheck(this, TableTreeStore);
    _defineProperty(this, "treeDataMap", /* @__PURE__ */new Map());
    _defineProperty(this, "expandAllRowIndex", void 0);
    this.treeDataMap = /* @__PURE__ */new Map();
  }
  _createClass(TableTreeStore, [{
    key: "initialTreeStore",
    value: function initialTreeStore(dataSource, columns, keys) {
      var _this$treeDataMap;
      (_this$treeDataMap = this.treeDataMap) === null || _this$treeDataMap === void 0 ? void 0 : _this$treeDataMap.clear();
      this.initialTreeDataMap(this.treeDataMap, dataSource, columns[0], keys);
    }
  }, {
    key: "getAllUniqueKeys",
    value: function getAllUniqueKeys(data, keys) {
      var arr = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
      for (var i = 0, len = data.length; i < len; i++) {
        var item = data[i];
        arr.push(get(item, keys.rowKey));
        var children = get(item, keys.childrenKey);
        if (children !== null && children !== void 0 && children.length) this.getAllUniqueKeys(children, keys, arr);
      }
      return arr;
    }
  }, {
    key: "toggleExpandData",
    value: function toggleExpandData(p, dataSource, keys) {
      if (!p) {
        log.error("EnhancedTable", "the node you want to toggleExpand doest not exist in `data`");
        return dataSource;
      }
      var rowValue = get(p.row, keys.rowKey);
      if (isUndefined(rowValue)) {
        log.error("EnhancedTable", "`rowKey` could be wrong, can not get rowValue from `data` by `rowKey`.");
        return [];
      }
      var childrenNodes = get(p.row, keys.childrenKey);
      if (childrenNodes === true) return dataSource;
      var r = this.treeDataMap.get(rowValue);
      r.rowIndex = p.rowIndex;
      r.expanded = !r.expanded;
      this.treeDataMap.set(rowValue, r);
      return this.updateExpandRow(r, dataSource, keys);
    }
  }, {
    key: "updateExpandRow",
    value: function updateExpandRow(changeRow, dataSource, keys) {
      var row = changeRow.row,
        rowIndex = changeRow.rowIndex,
        expanded = changeRow.expanded;
      var treeDataMap = this.treeDataMap;
      var childrenNodes = get(row, keys.childrenKey);
      if (!row || !childrenNodes) return dataSource;
      if (expanded) {
        updateChildrenRowState(treeDataMap, changeRow, expanded, keys);
        updateRowExpandLength(treeDataMap, row, childrenNodes.length, "expand", keys);
        dataSource.splice.apply(dataSource, [rowIndex + 1, 0].concat(childrenNodes));
      } else {
        updateChildrenRowState(treeDataMap, changeRow, expanded, keys);
        var len = changeRow.expandChildrenLength || childrenNodes.length;
        updateRowExpandLength(treeDataMap, row, -1 * len, "fold", keys);
        dataSource.splice(rowIndex + 1, len);
      }
      updateRowIndex(treeDataMap, dataSource, {
        rowKey: keys.rowKey,
        minRowIndex: rowIndex + 1
      });
      return dataSource;
    }
  }, {
    key: "getData",
    value: function getData(key) {
      return this.treeDataMap.get(key);
    }
  }, {
    key: "updateData",
    value: function updateData(rowValue, newRowData, dataSource, keys) {
      var newRowValue = get(newRowData, keys.rowKey);
      var rowState = this.treeDataMap.get(rowValue);
      if (!rowState || rowState.rowIndex === -1) {
        updateRowData(dataSource, rowValue, newRowData, {
          rowKey: keys.rowKey,
          childrenKey: keys.childrenKey
        });
        return -1;
      }
      if (get(newRowData, keys.childrenKey) === true) {
        var oldChildren = get(rowState.row, keys.childrenKey);
        if (oldChildren !== null && oldChildren !== void 0 && oldChildren.length) {
          for (var i = 0, len = oldChildren.length; i < len; i++) {
            var rowValue2 = get(oldChildren[i], keys.rowKey);
            var state = this.treeDataMap.get(rowValue2);
            if (state) this.treeDataMap["delete"](rowValue2);
          }
        }
      }
      var currentRowIndex = rowState.rowIndex;
      rowState.row = newRowData;
      rowState.id = newRowValue;
      if (rowState.parent) {
        var siblings = get(rowState.parent.row, keys.childrenKey);
        var index = siblings.findIndex(function (item) {
          return get(item, keys.rowKey) === rowValue;
        });
        siblings[index] = newRowData;
      }
      this.treeDataMap.set(newRowValue, rowState);
      if (rowValue !== newRowValue) this.treeDataMap["delete"](rowValue);
      return currentRowIndex;
    }
  }, {
    key: "remove",
    value: function remove(key, dataSource, keys) {
      var r = this.treeDataMap.get(key);
      if (r && r.rowIndex >= 0) {
        var removeNumber = (r.expandChildrenLength || 0) + 1;
        dataSource.splice(r.rowIndex, removeNumber);
        if (r.parent) {
          var siblings = get(r.parent.row, keys.childrenKey);
          var index = siblings.findIndex(function (item) {
            return get(item, keys.rowKey) === key;
          });
          siblings.splice(index, 1);
          updateRowExpandLength(this.treeDataMap, r.parent.row, -1 * removeNumber, "delete", keys);
        }
        this.treeDataMap["delete"](key);
        updateRowIndex(this.treeDataMap, dataSource, {
          minRowIndex: r.rowIndex,
          rowKey: keys.rowKey,
          type: "remove"
        });
      } else {
        log.warn("EnhancedTable", "Do not remove this node, which is not appeared.");
      }
      return dataSource;
    }
  }, {
    key: "appendTo",
    value: function appendTo(rowValue, newData, dataSource, keys) {
      var state = this.treeDataMap.get(rowValue);
      if (!this.validateDataExist(state, rowValue)) return dataSource;
      var children = get(state.row, keys.childrenKey);
      var isShowNewNode = state.expanded || !(children !== null && children !== void 0 && children.length);
      var tmpData = Array.isArray(newData) ? newData : [newData];
      var newChildrenData = [];
      var newChildrenStates = [];
      var firstNewChildrenIndex = -1;
      for (var i = 0, len = tmpData.length; i < len; i++) {
        var oneData = tmpData[i];
        var newRowValue = get(oneData, keys.rowKey);
        var mapState = this.treeDataMap.get(newRowValue);
        if (!this.validateDataDoubleExist(mapState, newRowValue)) {
          log.warn("Table", "Duplicated Data `".concat(newRowValue, "` has been removed."));
        } else {
          var rowIndex = isShowNewNode ? state.rowIndex + (state.expandChildrenLength || 0) + (i + 1) : -1;
          if (i === 0) firstNewChildrenIndex = rowIndex;
          var newState = {
            id: newRowValue,
            row: oneData,
            rowIndex: rowIndex,
            level: state.level + 1,
            expanded: false,
            expandChildrenLength: 0,
            disabled: false,
            path: _toConsumableArray(state.path),
            parent: state
          };
          newState.path = newState.path.concat(newState);
          newChildrenData.push(oneData);
          newChildrenStates.push(newState);
          this.treeDataMap.set(newRowValue, newState);
        }
      }
      if (!newChildrenData.length) return dataSource;
      if (children !== null && children !== void 0 && children.length) {
        state.row[keys.childrenKey] = state.row[keys.childrenKey].concat(newChildrenData);
      } else {
        state.row[keys.childrenKey] = newChildrenData;
        state.expanded = true;
      }
      if (isShowNewNode) {
        dataSource.splice.apply(dataSource, [firstNewChildrenIndex, 0].concat(newChildrenData));
        var newChildrenCount = newChildrenData.length || 1;
        updateRowExpandLength(this.treeDataMap, state.row, newChildrenCount, "insert", {
          rowKey: keys.rowKey,
          childrenKey: keys.childrenKey
        });
        updateRowIndex(this.treeDataMap, dataSource, {
          minRowIndex: firstNewChildrenIndex + newChildrenData.length - 1,
          rowKey: keys.rowKey,
          type: "add",
          count: 1
        });
      }
      return dataSource;
    }
  }, {
    key: "appendToRoot",
    value: function appendToRoot(newData, dataSource, keys) {
      var newDataSource = dataSource.concat(newData);
      var tmpNewData = Array.isArray(newData) ? newData : [newData];
      var dataSourceLen = dataSource.length;
      for (var i = 0, len = tmpNewData.length; i < len; i++) {
        var rowValue = get(tmpNewData[i], keys.rowKey);
        if (!rowValue) {
          log.error("Table", "`rowKey` could be wrong, can not get rowValue from `data` by `rowKey`.");
          continue;
        }
        var state = {
          id: rowValue,
          row: tmpNewData[i],
          rowIndex: dataSourceLen + i,
          level: 0,
          expanded: false,
          expandChildrenLength: 0,
          disabled: false
        };
        state.path = [state];
        this.treeDataMap.set(rowValue, state);
      }
      return newDataSource;
    }
  }, {
    key: "insertAfter",
    value: function insertAfter(rowValue, newData, dataSource, keys) {
      return this.insert(rowValue, newData, dataSource, keys, "after");
    }
  }, {
    key: "insertBefore",
    value: function insertBefore(rowValue, newData, dataSource, keys) {
      return this.insert(rowValue, newData, dataSource, keys, "before");
    }
  }, {
    key: "insert",
    value: function insert(rowValue, newData, dataSource, keys, type) {
      var state = this.treeDataMap.get(rowValue);
      if (!this.validateDataExist(state, rowValue)) return dataSource;
      var newRowValue = get(newData, keys.rowKey);
      var mapState = this.treeDataMap.get(newRowValue);
      if (!this.validateDataDoubleExist(mapState, newRowValue)) return dataSource;
      var rowIndex = type === "after" ? state.rowIndex + 1 : state.rowIndex;
      var newState = {
        id: newRowValue,
        row: newData,
        rowIndex: rowIndex,
        level: state.level,
        expanded: false,
        expandChildrenLength: 0,
        disabled: false,
        path: state.path.slice(0, -1),
        parent: state.parent
      };
      newState.path = newState.path.concat(newState);
      var dataIndex = type === "after" ? state.rowIndex + (state.expandChildrenLength + 1) : state.rowIndex;
      dataSource.splice(dataIndex, 0, newData);
      var distance = type === "after" ? 1 : 0;
      if (state.parent) {
        var childrenIndex = state.parent.row[keys.childrenKey].findIndex(function (t) {
          return rowValue === get(t, keys.rowKey);
        });
        state.parent.row[keys.childrenKey].splice(childrenIndex + distance, 0, newData);
        updateRowExpandLength(this.treeDataMap, state.parent.row, 1, "insert", keys);
      }
      this.treeDataMap.set(newRowValue, newState);
      updateRowIndex(this.treeDataMap, dataSource, {
        rowKey: keys.rowKey,
        minRowIndex: state.rowIndex + 1,
        type: "add"
      });
      return dataSource;
    }
  }, {
    key: "swapData",
    value: function swapData(dataSource, params, keys) {
      var startIndex = params.currentIndex;
      var endIndex = params.targetIndex;
      if (startIndex === endIndex) return {
        dataSource: dataSource,
        result: true
      };
      var startRowValue = get(params.current, keys.rowKey);
      var endRowValue = get(params.target, keys.rowKey);
      var startState = this.treeDataMap.get(startRowValue);
      var endState = this.treeDataMap.get(endRowValue);
      if (startState.level !== endState.level) {
        return {
          dataSource: dataSource,
          result: false,
          code: TABLE_TREE_ERROR_CODE_NOT_SAME_LEVEL.code,
          reason: TABLE_TREE_ERROR_CODE_NOT_SAME_LEVEL.reason
        };
      }
      var startLastIndex = startIndex + startState.expandChildrenLength + 1;
      var endLastIndex = endIndex + endState.expandChildrenLength + 1;
      var startRowList = dataSource.slice(startIndex, startLastIndex);
      var endRowList = dataSource.slice(endIndex, endLastIndex);
      if (startIndex > endIndex) {
        var middleRowList = dataSource.slice(endLastIndex, startIndex);
        var allSwapList = startRowList.concat(endRowList, middleRowList);
        dataSource.splice(endIndex, allSwapList.length);
        dataSource.splice.apply(dataSource, [endIndex, 0].concat(_toConsumableArray(allSwapList)));
        updateRowIndex(this.treeDataMap, dataSource, {
          rowKey: keys.rowKey,
          minRowIndex: endIndex,
          maxRowIndex: startLastIndex
        });
      } else {
        var _middleRowList = dataSource.slice(startLastIndex, endIndex);
        var _allSwapList = _middleRowList.concat(endRowList, startRowList);
        dataSource.splice(startIndex, _allSwapList.length);
        dataSource.splice.apply(dataSource, [startIndex, 0].concat(_toConsumableArray(_allSwapList)));
        updateRowIndex(this.treeDataMap, dataSource, {
          rowKey: keys.rowKey,
          minRowIndex: startIndex,
          maxRowIndex: endLastIndex
        });
      }
      if (startState.parent) {
        var children = startState.parent.row[keys.childrenKey];
        var count = 0;
        var targetIndex = -1;
        var currentIndex = -1;
        for (var i = 0, len = children.length; i < len; i++) {
          if (get(children[i], keys.rowKey) === startRowValue) {
            targetIndex = i;
            count += 1;
          }
          if (get(children[i], keys.rowKey) === endRowValue) {
            currentIndex = i;
            count += 1;
          }
          if (count >= 2) break;
        }
        children[targetIndex] = params.target;
        children[currentIndex] = params.current;
      }
      return {
        dataSource: dataSource,
        result: true
      };
    }
  }, {
    key: "expandAll",
    value: function expandAll(dataSource, keys) {
      var _this = this;
      this.expandAllRowIndex = 0;
      var expandLoop = function expandLoop(dataSource2, keys2) {
        var newData = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
        var parentExpanded = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
        var parent = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
        for (var i = 0, len = dataSource2.length; i < len; i++) {
          var item = dataSource2[i];
          var rowValue = get(item, keys2.rowKey);
          var state = _this.treeDataMap.get(rowValue);
          var children = get(item, keys2.childrenKey);
          var originalExpanded = state.expanded;
          state.rowIndex = _this.expandAllRowIndex;
          if (children !== true && children !== null && children !== void 0 && children.length) state.expanded = true;
          state.expandChildrenLength = (children === null || children === void 0 ? void 0 : children.length) || 0;
          _this.expandAllRowIndex += 1;
          if (!parentExpanded) newData.push(item);
          _this.treeDataMap.set(rowValue, state);
          if (children !== null && children !== void 0 && children.length && !originalExpanded) {
            var tmpParent = parent;
            while ((_tmpParent = tmpParent) !== null && _tmpParent !== void 0 && _tmpParent.row) {
              var _tmpParent;
              tmpParent.expandChildrenLength += children.length;
              _this.treeDataMap.set(tmpParent.id, tmpParent);
              tmpParent = tmpParent.parent;
            }
            expandLoop(children, keys2, newData, originalExpanded, state);
          }
        }
        return newData;
      };
      return expandLoop(dataSource, keys);
    }
  }, {
    key: "foldAll",
    value: function foldAll(dataSource, keys) {
      var newData = [];
      for (var i = 0, len = dataSource.length; i < len; i++) {
        var item = dataSource[i];
        var rowValue = get(item, keys.rowKey);
        var state = this.treeDataMap.get(rowValue);
        state.rowIndex = state.level === 0 ? i : -1;
        state.expanded = false;
        state.expandChildrenLength = 0;
        if (state.level === 0) newData.push(item);
        var children = get(item, keys.childrenKey);
        if (children !== null && children !== void 0 && children.length) this.foldAll(children, keys);
      }
      return newData;
    }
  }, {
    key: "getTreeNode",
    value: function getTreeNode(dataSource, keys) {
      var treeData = [];
      for (var i = 0, len = dataSource.length; i < len; i++) {
        var item = dataSource[i];
        var rowValue = get(item, keys.rowKey);
        var state = this.treeDataMap.get(rowValue);
        if (state.level === 0) treeData.push(item);
      }
      return treeData;
    }
  }, {
    key: "getTreeExpandedRow",
    value: function getTreeExpandedRow(dataSource, keys) {
      var _this2 = this;
      var type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "data";
      var arr = [];
      dataSource.forEach(function (item) {
        var rowValue = get(item, keys.rowKey);
        var rowState = _this2.treeDataMap.get(rowValue);
        if (!rowState.expanded) return;
        if (type === "unique") arr.push(rowValue);else if (type === "data") arr.push(item);else arr.push(rowState);
      });
      return arr;
    }
  }, {
    key: "initialTreeDataMap",
    value: function initialTreeDataMap(treeDataMap, dataSource, column, keys) {
      var level = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
      var parent = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;
      for (var i = 0, len = dataSource.length; i < len; i++) {
        var item = dataSource[i];
        var rowValue = get(item, keys.rowKey);
        if (isUndefined(rowValue)) {
          log.error("EnhancedTable", "`rowKey` could be wrong, can not get rowValue from `data` by `rowKey`.");
          return;
        }
        var children = get(item, keys.childrenKey);
        var state = {
          id: rowValue,
          row: item,
          rowIndex: level === 0 ? i : -1,
          level: level,
          expanded: false,
          expandChildrenLength: 0,
          disabled: isRowSelectedDisabled(column, item, i),
          parent: parent
        };
        state.path = parent ? parent.path.concat(state) : [state];
        treeDataMap.set(rowValue, state);
        if (children !== null && children !== void 0 && children.length) this.initialTreeDataMap(treeDataMap, children, column, keys, level + 1, state);
      }
    }
  }, {
    key: "updateDisabledState",
    value: function updateDisabledState(dataSource, column, keys) {
      for (var i = 0, len = dataSource.length; i < len; i++) {
        var item = dataSource[i];
        var rowValue = get(item, keys.rowKey);
        if (isUndefined(rowValue)) {
          log.error("EnhancedTable", "`rowKey` could be wrong, can not get rowValue from `data` by `rowKey`.");
          return;
        }
        var state = this.treeDataMap.get(rowValue);
        state.disabled = isRowSelectedDisabled(column, item, i);
        this.treeDataMap.set(rowValue, state);
        var children = get(item, keys.childrenKey);
        if (children !== null && children !== void 0 && children.length) this.updateDisabledState(children, column, keys);
      }
    }
  }, {
    key: "validateDataExist",
    value: function validateDataExist(state, rowValue) {
      if (!state) {
        log.warn("EnhancedTable", "".concat(rowValue, " does not exist."));
        return false;
      }
      return true;
    }
  }, {
    key: "validateDataDoubleExist",
    value: function validateDataDoubleExist(state, rowValue) {
      if (state) {
        log.warn("EnhancedTable", "Duplicated Key. ".concat(rowValue, " already exists."));
        return false;
      }
      return true;
    }
  }]);
  return TableTreeStore;
}();
function updateRowExpandLength(treeDataMap, row, distance, type, keys) {
  var tmp = row;
  while (tmp) {
    var _state$parent;
    var state = treeDataMap.get(get(tmp, keys.rowKey));
    var expandLen = (state.expandChildrenLength || 0) + distance;
    state.expandChildrenLength = Math.max(0, expandLen);
    tmp = state === null || state === void 0 ? void 0 : (_state$parent = state.parent) === null || _state$parent === void 0 ? void 0 : _state$parent.row;
  }
  if (type === "fold") clearRowExpandLength(treeDataMap, row, keys);
}
function clearRowExpandLength(treeDataMap, row, keys) {
  var children = get(row, keys.childrenKey);
  if (children !== null && children !== void 0 && children.length) {
    children.forEach(function (item) {
      var state = treeDataMap.get(get(item, keys.rowKey));
      if (!state) return;
      state.expandChildrenLength = 0;
      clearRowExpandLength(treeDataMap, state.row, keys);
    });
  }
}
function updateChildrenRowState(treeDataMap, rowState, expanded, keys) {
  var row = rowState.row,
    rowIndex = rowState.rowIndex;
  var childrenNodes = get(row, keys.childrenKey);
  childrenNodes.forEach(function (item, kidRowIndex) {
    var rowValue = get(item, keys.rowKey);
    var index = expanded ? rowIndex + 1 + kidRowIndex : -1;
    var curState = treeDataMap.get(rowValue);
    var newState = _objectSpread(_objectSpread({}, curState), {}, {
      row: item,
      rowIndex: index,
      expanded: false,
      parent: rowState
    });
    treeDataMap.set(rowValue, newState);
    if (!expanded) {
      var children = get(item, keys.childrenKey);
      if (children !== null && children !== void 0 && children.length) {
        updateChildrenRowState(treeDataMap, _objectSpread(_objectSpread({}, newState), {}, {
          rowIndex: -1,
          expanded: false
        }), expanded, keys);
      }
    }
  });
}
function updateRowData(data, key, newData, keys) {
  for (var i = 0, len = data.length; i < len; i++) {
    var item = data[i];
    if (get(item, keys.rowKey) === key) {
      data[i] = newData;
      return;
    }
    var children = get(item, keys.childrenKey) || [];
    if (children !== null && children !== void 0 && children.length) updateRowData(children, key, newData, keys);
  }
}
function updateRowIndex(treeDataMap, dataSource, extra) {
  var start = extra.minRowIndex || 0;
  var end = extra.maxRowIndex || dataSource.length;
  for (var rowIndex = start; rowIndex < end; rowIndex++) {
    var item = dataSource[rowIndex];
    var state = treeDataMap.get(get(item, extra.rowKey));
    if (!state) log.warn("Table", "tree map went wrong");
    state.rowIndex = rowIndex + ((extra === null || extra === void 0 ? void 0 : extra.count) || 1) - 1;
  }
}

export { TABLE_TREE_ERROR_CODE_NOT_SAME_LEVEL, clearRowExpandLength, TableTreeStore as default, updateChildrenRowState, updateRowData, updateRowExpandLength, updateRowIndex };
//# sourceMappingURL=tree-store.js.map
