"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.NestedTableNodeState = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _bexCore = require("@wix/bex-core");
var _mobx = require("mobx");
var _NestedTableNodeStateBIReporter = require("./NestedTableNodeStateBIReporter");
var _getNodeOrLeaf = require("./getNodeOrLeaf");
var _NestedTableNodeStateOptimisticActions = require("./NestedTableNodeStateOptimisticActions");
class NestedTableNodeState {
  constructor(params) {
    (0, _defineProperty2.default)(this, "nestedTable", void 0);
    (0, _defineProperty2.default)(this, "node", void 0);
    (0, _defineProperty2.default)(this, "levelDescriptor", void 0);
    (0, _defineProperty2.default)(this, "parentNode", void 0);
    (0, _defineProperty2.default)(this, "parent", void 0);
    (0, _defineProperty2.default)(this, "bi", void 0);
    (0, _defineProperty2.default)(this, "multi", void 0);
    (0, _defineProperty2.default)(this, "_rowNum", void 0);
    (0, _defineProperty2.default)(this, "initTask", new _bexCore.TaskState());
    (0, _defineProperty2.default)(this, "parentKeyToChildrenMap", new Map());
    (0, _defineProperty2.default)(this, "parentKeyToChildrenMapAtom", (0, _mobx.createAtom)('parentKeyToChildrenMapAtom'));
    (0, _defineProperty2.default)(this, "retryErrorState", () => this.node.collection.retryErrorState());
    this.nestedTable = params.nestedTable;
    this.node = params.node;
    this.parentNode = params.parentNode;
    this.parent = params.parent;
    this.levelDescriptor = params.levelDescriptor;
    this.bi = new _NestedTableNodeStateBIReporter.NestedTableNodeStateBIReporter(this);
    this.multi = new _bexCore.MultiCollectionSupport({
      collections: [this.node.collection]
    });
    (0, _mobx.makeObservable)(this, {
      keyedItems: _mobx.computed,
      _keyedItemsMap: _mobx.computed,
      _allKeyedItemsMap: _mobx.computed,
      _allKeyedItems: _mobx.computed,
      _keyedItemsIfExpanded: _mobx.computed,
      _isNotExpandableWhenEmpty: _mobx.computed,
      init: _mobx.action,
      createNode: _mobx.action,
      _preRegisterAll: _mobx.action,
      _toggleExpand: _mobx.action,
      _notify: _mobx.action,
      _notifyAll: _mobx.action,
      deepestBranchDepth: _mobx.computed,
      unprocessedMap: _mobx.computed,
      getKeyedItem: _mobx.action,
      hasExpandableItems: _mobx.computed,
      _childrenCount: _mobx.computed
    });
    this._register();
  }
  get collection() {
    return this.node.collection;
  }
  get unprocessedMap() {
    const {
      collection: {
        result
      }
    } = this;
    const {
      _pages,
      itemKey,
      _pagesAtom
    } = result;
    _pagesAtom.reportObserved();
    return new Map(_pages.unprocessed.flatMap(page => page.map(item => {
      const key = itemKey(item);
      return [key, item];
    })));
  }
  get children() {
    return this.collection;
  }
  get optimisticActions() {
    return new _NestedTableNodeStateOptimisticActions.NestedTableNodeStateOptimisticActions(this);
  }
  get flatModeCollection() {
    var _this$nestedTable$wra;
    return (_this$nestedTable$wra = this.nestedTable.wrapper.flat.sections.find(section => section.levelDescriptors.includes(this.levelDescriptor))) == null ? void 0 : _this$nestedTable$wra.collection;
  }
  get depth() {
    var _this$parentNode;
    return ((_this$parentNode = this.parentNode) == null ? void 0 : _this$parentNode.childrenDepth) ?? 0;
  }
  get childrenDepth() {
    return this.levelDescriptor.depth;
  }
  get deepestBranchDepth() {
    const {
      node,
      parentKeyToChildrenMap,
      parentKeyToChildrenMapAtom
    } = this;
    const {
      collection: {
        result: {
          keyedItems
        }
      }
    } = node;
    parentKeyToChildrenMapAtom.reportObserved();
    return keyedItems.reduce((acc, keyedItem) => {
      var _parentKeyToChildrenM;
      return Math.max(acc, ((_parentKeyToChildrenM = parentKeyToChildrenMap.get(keyedItem.id)) == null ? void 0 : _parentKeyToChildrenM.deepestBranchDepth) ?? 0);
    }, 0) + (keyedItems.length ? 1 : 0);
  }
  get hasExpandableItems() {
    const {
      parentKeyToChildrenMap,
      parentKeyToChildrenMapAtom
    } = this;
    parentKeyToChildrenMapAtom.reportObserved();
    return this.node.collection.result.keyedItems.some(item => {
      var _parentKeyToChildrenM2;
      return (((_parentKeyToChildrenM2 = parentKeyToChildrenMap.get(item.id)) == null ? void 0 : _parentKeyToChildrenM2._childrenCount) ?? 0) > 0;
    });
  }
  get _childrenCount() {
    return this.node.collection.result.keyedItems.length ?? 0;
  }
  get _expanded() {
    return this.node._expanded;
  }
  get columns() {
    return this.levelDescriptor.columns;
  }
  get renderMainColumn() {
    return this.levelDescriptor.renderMainColumn;
  }
  get showHoverHighlight() {
    return this.node.hoveredOrParentHovered;
  }
  _changeHover(hovered) {
    this.node._changeHover(hovered);
  }
  get showEmptyState() {
    return this.node.collection.showEmptyState;
  }
  get showLoadingState() {
    return this.node.collection.showInitialLoader || this.node.collection.showRefreshLoader;
  }
  get showErrorState() {
    return this.node.collection.showErrorState;
  }
  get errorStatus() {
    return this.node.collection.result.errorStatus;
  }
  get _isNotExpandableWhenEmpty() {
    const {
      nestedTable: {
        isFetchAllAborted
      },
      node: {
        collection: {
          showEmptyState
        }
      }
    } = this;
    return !isFetchAllAborted && showEmptyState;
  }
  _isExpandableActionDisabled(item) {
    var _this$levelDescriptor, _this$levelDescriptor2;
    return ((_this$levelDescriptor = (_this$levelDescriptor2 = this.levelDescriptor).expandable) == null ? void 0 : _this$levelDescriptor.call(_this$levelDescriptor2, item)) === false;
  }
  isNotExpandable(item) {
    return this._isNotExpandableWhenEmpty || this._isExpandableActionDisabled(item);
  }
  get _keyedItemsIfExpanded() {
    const {
      parent,
      nestedTable: {
        isFetchAllAborted
      },
      _expanded,
      node: {
        collection: {
          showRefreshLoader,
          showEmptyState,
          showErrorState
        }
      }
    } = this;
    if (!_expanded) {
      return [];
    }
    return [...this.keyedItems, ...(parent && isFetchAllAborted && (showRefreshLoader || showEmptyState || showErrorState) ? new Array(1).fill(null).map((_, index) => ({
      id: `placeholder-states-${parent.key}`,
      key: `placeholder-states-${parent.key}`,
      index,
      pageIndex: 0,
      indexWithinPage: index,
      item: {
        state: this,
        originalKeyedItem: undefined
      }
    })) : [])];
  }
  get _keyedItemsMap() {
    return new Map(this.keyedItems.map(keyedItem => [keyedItem.key, keyedItem]));
  }
  get _allKeyedItemsMap() {
    return new Map(this._getKeyedItems({
      onlyExpanded: false
    }).map(keyedItem => [keyedItem.key, keyedItem]));
  }
  get _allKeyedItems() {
    return Array.from(this._allKeyedItemsMap.values());
  }
  _getKeyedItems({
    onlyExpanded
  }) {
    const {
      node,
      parentKeyToChildrenMap,
      parentKeyToChildrenMapAtom
    } = this;
    const {
      collection: {
        result: {
          keyedItems
        }
      }
    } = node;
    parentKeyToChildrenMapAtom.reportObserved();
    return keyedItems.flatMap(keyedItem => {
      const childrenNode = parentKeyToChildrenMap.get(keyedItem.key);
      return [{
        ...keyedItem,
        item: {
          state: this,
          originalKeyedItem: keyedItem
        }
      }, ...(childrenNode ? onlyExpanded ? childrenNode._keyedItemsIfExpanded : childrenNode._allKeyedItems : [])];
    }).map((keyedItem, index) => ({
      ...keyedItem,
      index
    }));
  }
  get keyedItems() {
    return this._getKeyedItems({
      onlyExpanded: true
    });
  }
  getKeyedItem(key) {
    return this._keyedItemsMap.get(key);
  }
  getDescendants() {
    const {
      collection
    } = this;
    return collection.result.keyedItems.flatMap(keyedItem => {
      const node = (0, _getNodeOrLeaf.getNodeOrLeaf)(this, keyedItem);
      return [node, ...node.getDescendants()];
    });
  }
  _getNode(key) {
    const node = this._keyedItemsMap.get(key);
    return node == null ? void 0 : node.item.state.parentKeyToChildrenMap.get(key);
  }
  getParent() {
    return this.parentNode;
  }
  getData() {
    const {
      parent,
      parentNode
    } = this;
    if (parent == null || parentNode == null) {
      return null;
    }
    return parentNode.collection.getItem(parent.key);
  }
  toggleExpand() {
    this._toggleExpand();
  }
  get expanded() {
    return this._expanded;
  }
  getKeyedItemByIndex(ind) {
    return this.keyedItems[ind];
  }
  _register() {
    const {
      parent,
      parentNode
    } = this;
    if (parent == null || parentNode == null) {
      return;
    }
    parentNode.parentKeyToChildrenMap.set(parent.key, this);
    return () => {
      parentNode.parentKeyToChildrenMap.delete(parent.key);
    };
  }
  async _refreshAll() {
    const {
      collection
    } = this;
    collection._resetReactQuery();
    await collection.moveToFirstPage();
    const keyedItems = collection.result.keyedItems;
    for (const keyedItem of keyedItems) {
      const node = this.createNode({
        parent: keyedItem
      });
      if (node == null) {
        continue;
      }
      await node._refreshAll();
    }
    if (this.childrenDepth === 0 || this.node._notifyAll) {
      this._notifyAll();
    }
  }
  async _toggleExpand() {
    var _this$parentNode2;
    const promise = this.node._toggleExpand();
    (_this$parentNode2 = this.parentNode) == null || _this$parentNode2.parentKeyToChildrenMapAtom.reportChanged();
    await promise;
    (0, _mobx.runInAction)(() => {
      var _this$parentNode3;
      (_this$parentNode3 = this.parentNode) == null || _this$parentNode3.parentKeyToChildrenMapAtom.reportChanged();
    });
  }
  async _preRegisterAll() {
    const {
      node
    } = this;
    const {
      collection: {
        result: {
          keyedItems
        }
      }
    } = node;
    await Promise.all(keyedItems.map(async keyedItem => {
      const state = this.createNode({
        parent: keyedItem
      });
      if (state == null) {
        return;
      }
      const dispose = state.init();
      await state.initTask.status.promise;
      dispose();
    }));
  }
  _notify() {
    const {
      parentKeyToChildrenMapAtom
    } = this;
    parentKeyToChildrenMapAtom.reportChanged();
  }
  _notifyAll() {
    const {
      parentKeyToChildrenMap
    } = this;
    this._notify();
    parentKeyToChildrenMap.forEach(state => {
      state._notifyAll();
    });
  }
  _cleanupStaleNodes() {
    return (0, _mobx.reaction)(() => this.collection.result.keyedItems, keyedItems => {
      const {
        parentKeyToChildrenMap
      } = this;
      // remove children that are not in the collection
      const keys = new Set(keyedItems.map(item => item.key));
      const mapKeys = Array.from(parentKeyToChildrenMap.keys());
      for (const key of mapKeys) {
        if (keys.has(key)) {
          continue;
        }
        parentKeyToChildrenMap.delete(key);
      }
    });
  }
  init({
    skipCollectionInit
  } = {}) {
    const {
      node,
      initTask,
      nestedTable,
      collection
    } = this;
    const {
      nestedTableDragAndDrop
    } = nestedTable;
    const disposers = [node.init({
      skipCollectionInit
    }), nestedTableDragAndDrop == null ? void 0 : nestedTableDragAndDrop.initCollection(collection), this._cleanupStaleNodes()];
    initTask.runOnce(async () => {
      node.initTask.runOnce();
      await node.initTask.status.promise;
      await (0, _mobx.runInAction)(async () => {
        if (!nestedTable.isFetchAllAborted) {
          await this._preRegisterAll();
          if (this.childrenDepth === 0 || node._notifyAll) {
            this._notifyAll();
          }
        }
        return;
      });
    });
    return () => {
      disposers.forEach(d => d == null ? void 0 : d());
    };
  }
  createNode({
    parent,
    notifyAll
  }) {
    const {
      nestedTable,
      node,
      childrenDepth,
      parentKeyToChildrenMap
    } = this;
    const existing = parentKeyToChildrenMap.get(parent.key);
    if (existing != null) {
      return existing;
    }
    const nextLevelDescriptor = nestedTable.levels[childrenDepth + 1];
    if (nextLevelDescriptor == null) {
      return null;
    }
    const nextLevelNode = node._createNode(parent, {
      levelDescriptor: nextLevelDescriptor,
      notifyAll
    });
    if (nextLevelNode == null) {
      return null;
    }
    return new NestedTableNodeState({
      parent,
      parentNode: this,
      nestedTable,
      node: nextLevelNode,
      levelDescriptor: nextLevelDescriptor
    });
  }
}
exports.NestedTableNodeState = NestedTableNodeState;
//# sourceMappingURL=NestedTableNodeState.js.map