text: import { _, Events, RowNode } from "@ag-grid-community/core";
  var ClientSideNodeManager = /** @class */ (function () {
      function ClientSideNodeManager(rootNode, gridOptionsWrapper, context, eventService, columnController, gridApi, columnApi, selectionController) {
          this.nextId = 0;
          // when user is provide the id's, we also keep a map of ids to row nodes for convenience
          this.allNodesMap = {};
          this.rootNode = rootNode;
          this.gridOptionsWrapper = gridOptionsWrapper;
          this.context = context;
          this.eventService = eventService;
          this.columnController = columnController;
          this.gridApi = gridApi;
          this.columnApi = columnApi;
          this.selectionController = selectionController;
          this.rootNode.group = true;
          this.rootNode.level = -1;
          this.rootNode.id = ClientSideNodeManager.ROOT_NODE_ID;
          this.rootNode.allLeafChildren = [];
          this.rootNode.childrenAfterGroup = [];
          this.rootNode.childrenAfterSort = [];
          this.rootNode.childrenAfterFilter = [];
          // if we make this class a bean, then can annotate postConstruct
          this.postConstruct();
      }
      // @PostConstruct - this is not a bean, so postConstruct called by constructor
      ClientSideNodeManager.prototype.postConstruct = function () {
          // func below doesn't have 'this' pointer, so need to pull out these bits
          this.suppressParentsInRowNodes = this.gridOptionsWrapper.isSuppressParentsInRowNodes();
          this.isRowMasterFunc = this.gridOptionsWrapper.getIsRowMasterFunc();
          this.doingTreeData = this.gridOptionsWrapper.isTreeData();
          this.doingMasterDetail = this.gridOptionsWrapper.isMasterDetail();
      };
      ClientSideNodeManager.prototype.getCopyOfNodesMap = function () {
          return _.cloneObject(this.allNodesMap);
      };
      ClientSideNodeManager.prototype.getRowNode = function (id) {
          return this.allNodesMap[id];
      };
      ClientSideNodeManager.prototype.setRowData = function (rowData) {
          this.rootNode.childrenAfterFilter = null;
          this.rootNode.childrenAfterGroup = null;
          this.rootNode.childrenAfterSort = null;
          this.rootNode.childrenMapped = null;
          this.rootNode.updateHasChildren();
          this.nextId = 0;
          this.allNodesMap = {};
          if (!rowData) {
              this.rootNode.allLeafChildren = [];
              this.rootNode.childrenAfterGroup = [];
              return;
          }
          // kick off recursion
          // we add rootNode as the parent, however if using ag-grid-enterprise, the grouping stage
          // sets the parent node on each row (even if we are not grouping). so setting parent node
          // here is for benefit of ag-grid-community users
          this.rootNode.allLeafChildren = this.recursiveFunction(rowData, this.rootNode, ClientSideNodeManager.TOP_LEVEL);
      };
      ClientSideNodeManager.prototype.updateRowData = function (rowDataTran, rowNodeOrder) {
          var rowNodeTransaction = {
              remove: [],
              update: [],
              add: []
          };
          var nodesToUnselect = [];
          this.executeAdd(rowDataTran, rowNodeTransaction);
          this.executeRemove(rowDataTran, rowNodeTransaction, nodesToUnselect);
          this.executeUpdate(rowDataTran, rowNodeTransaction, nodesToUnselect);
          this.updateSelection(nodesToUnselect);
          if (rowNodeOrder) {
              _.sortRowNodesByOrder(this.rootNode.allLeafChildren, rowNodeOrder);
          }
          return rowNodeTransaction;
      };
      ClientSideNodeManager.prototype.updateSelection = function (nodesToUnselect) {
          var selectionChanged = nodesToUnselect.length > 0;
          if (selectionChanged) {
              nodesToUnselect.forEach(function (rowNode) {
                  rowNode.setSelected(false, false, true);
              });
          }
          // we do this regardless of nodes to unselect or not, as it's possible
          // a new node was inserted, so a parent that was previously selected (as all
          // children were selected) should not be tri-state (as new one unselected against
          // all other selected children).
          this.selectionController.updateGroupsFromChildrenSelections();
          if (selectionChanged) {
              var event_1 = {
                  type: Events.EVENT_SELECTION_CHANGED,
                  api: this.gridApi,
                  columnApi: this.columnApi
              };
              this.eventService.dispatchEvent(event_1);
          }
      };
      ClientSideNodeManager.prototype.executeAdd = function (rowDataTran, rowNodeTransaction) {
          var _this = this;
          var add = rowDataTran.add, addIndex = rowDataTran.addIndex;
          if (_.missingOrEmpty(add)) {
              return;
          }
          var useIndex = typeof addIndex === 'number' && addIndex >= 0;
          if (useIndex) {
              // items get inserted in reverse order for index insertion
              add.reverse().forEach(function (item) {
                  var newRowNode = _this.addRowNode(item, addIndex);
                  rowNodeTransaction.add.push(newRowNode);
              });
          }
          else {
              add.forEach(function (item) {
                  var newRowNode = _this.addRowNode(item);
                  rowNodeTransaction.add.push(newRowNode);
              });
          }
      };
      ClientSideNodeManager.prototype.executeRemove = function (rowDataTran, rowNodeTransaction, nodesToUnselect) {
          var _this = this;
          var remove = rowDataTran.remove;
          if (_.missingOrEmpty(remove)) {
              return;
          }
          var rowIdsRemoved = {};
          remove.forEach(function (item) {
              var rowNode = _this.lookupRowNode(item);
              if (!rowNode) {
                  return;
              }
              // do delete - setting 'suppressFinishActions = true' to ensure EVENT_SELECTION_CHANGED is not raised for
              // each row node updated, instead it is raised once by the calling code if any selected nodes exist.
              if (rowNode.isSelected()) {
                  nodesToUnselect.push(rowNode);
              }
              // so row renderer knows to fade row out (and not reposition it)
              rowNode.clearRowTop();
              // NOTE: were we could remove from allLeaveChildren, however _.removeFromArray() is expensive, especially
              // if called multiple times (eg deleting lots of rows) and if allLeafChildren is a large list
              rowIdsRemoved[rowNode.id] = true;
              // _.removeFromArray(this.rootNode.allLeafChildren, rowNode);
              delete _this.allNodesMap[rowNode.id];
              rowNodeTransaction.remove.push(rowNode);
          });
          this.rootNode.allLeafChildren = this.rootNode.allLeafChildren.filter(function (rowNode) { return !rowIdsRemoved[rowNode.id]; });
      };
      ClientSideNodeManager.prototype.executeUpdate = function (rowDataTran, rowNodeTransaction, nodesToUnselect) {
          var _this = this;
          var update = rowDataTran.update;
          if (_.missingOrEmpty(update)) {
              return;
          }
          update.forEach(function (item) {
              var rowNode = _this.lookupRowNode(item);
              if (!rowNode) {
                  return;
              }
              rowNode.updateData(item);
              if (!rowNode.selectable && rowNode.isSelected()) {
                  nodesToUnselect.push(rowNode);
              }
              _this.setMasterForRow(rowNode, item, ClientSideNodeManager.TOP_LEVEL, false);
              rowNodeTransaction.update.push(rowNode);
          });
      };
      ClientSideNodeManager.prototype.addRowNode = function (data, index) {
          var newNode = this.createNode(data, this.rootNode, ClientSideNodeManager.TOP_LEVEL);
          if (_.exists(index)) {
              _.insertIntoArray(this.rootNode.allLeafChildren, newNode, index);
          }
          else {
              this.rootNode.allLeafChildren.push(newNode);
          }
          return newNode;
      };
      ClientSideNodeManager.prototype.lookupRowNode = function (data) {
          var rowNodeIdFunc = this.gridOptionsWrapper.getRowNodeIdFunc();
          var rowNode;
          if (_.exists(rowNodeIdFunc)) {
              // find rowNode using id
              var id = rowNodeIdFunc(data);
              rowNode = this.allNodesMap[id];
              if (!rowNode) {
                  console.error("ag-Grid: could not find row id=" + id + ", data item was not found for this id");
                  return null;
              }
          }
          else {
              // find rowNode using object references
              rowNode = _.find(this.rootNode.allLeafChildren, function (rowNode) { return rowNode.data === data; });
              if (!rowNode) {
                  console.error("ag-Grid: could not find data item as object was not found", data);
                  return null;
              }
          }
          return rowNode;
      };
      ClientSideNodeManager.prototype.recursiveFunction = function (rowData, parent, level) {
          var _this = this;
          // make sure the rowData is an array and not a string of json - this was a commonly reported problem on the forum
          if (typeof rowData === 'string') {
              console.warn('ag-Grid: rowData must be an array, however you passed in a string. If you are loading JSON, make sure you convert the JSON string to JavaScript objects first');
              return;
          }
          var rowNodes = [];
          rowData.forEach(function (dataItem) {
              var node = _this.createNode(dataItem, parent, level);
              rowNodes.push(node);
          });
          return rowNodes;
      };
      ClientSideNodeManager.prototype.createNode = function (dataItem, parent, level) {
          var node = new RowNode();
          this.context.createBean(node);
          node.group = false;
          this.setMasterForRow(node, dataItem, level, true);
          if (parent && !this.suppressParentsInRowNodes) {
              node.parent = parent;
          }
          node.level = level;
          node.setDataAndId(dataItem, this.nextId.toString());
          if (this.allNodesMap[node.id]) {
              console.warn("ag-grid: duplicate node id '" + node.id + "' detected from getRowNodeId callback, this could cause issues in your grid.");
          }
          this.allNodesMap[node.id] = node;
          this.nextId++;
          return node;
      };
      ClientSideNodeManager.prototype.setMasterForRow = function (rowNode, data, level, setExpanded) {
          if (this.doingTreeData) {
              rowNode.setMaster(false);
              if (setExpanded) {
                  rowNode.expanded = false;
              }
          }
          else {
              // this is the default, for when doing grid data
              if (this.doingMasterDetail) {
                  // if we are doing master detail, then the
                  // default is that everything can be a Master Row.
                  if (this.isRowMasterFunc) {
                      rowNode.setMaster(this.isRowMasterFunc(data));
                  }
                  else {
                      rowNode.setMaster(true);
                  }
              }
              else {
                  rowNode.setMaster(false);
              }
              if (setExpanded) {
                  var rowGroupColumns = this.columnController.getRowGroupColumns();
                  var numRowGroupColumns = rowGroupColumns ? rowGroupColumns.length : 0;
                  // need to take row group into account when determining level
                  var masterRowLevel = level + numRowGroupColumns;
                  rowNode.expanded = rowNode.master ? this.isExpanded(masterRowLevel) : false;
              }
          }
      };
      ClientSideNodeManager.prototype.isExpanded = function (level) {
          var expandByDefault = this.gridOptionsWrapper.getGroupDefaultExpanded();
          if (expandByDefault === -1) {
              return true;
          }
          else {
              return level < expandByDefault;
          }
      };
      // this is only used for doing legacy tree data
      ClientSideNodeManager.prototype.setLeafChildren = function (node) {
          node.allLeafChildren = [];
          if (node.childrenAfterGroup) {
              node.childrenAfterGroup.forEach(function (childAfterGroup) {
                  if (childAfterGroup.group) {
                      if (childAfterGroup.allLeafChildren) {
                          childAfterGroup.allLeafChildren.forEach(function (leafChild) { return node.allLeafChildren.push(leafChild); });
                      }
                  }
                  else {
                      node.allLeafChildren.push(childAfterGroup);
                  }
              });
          }
      };
      ClientSideNodeManager.TOP_LEVEL = 0;
      ClientSideNodeManager.ROOT_NODE_ID = 'ROOT_NODE_ID';
      return ClientSideNodeManager;
  }());
  export { ClientSideNodeManager };
  