text: define(["require", "exports", "./Selection.types", "../EventGroup"], function (require, exports, Selection_types_1, EventGroup_1) {
      "use strict";
      Object.defineProperty(exports, "__esModule", { value: true });
      exports.Selection = void 0;
      /**
       * {@docCategory Selection}
       */
      var Selection = /** @class */ (function () {
          /**
           * Create a new Selection. If `TItem` does not have a `key` property, you must provide an options
           * object with a `getKey` implementation. Providing options is optional otherwise.
           * (At most one `options` object is accepted.)
           */
          function Selection() {
              var options = []; // Otherwise, arguments require options with `getKey`.
              for (var _i = 0 // Otherwise, arguments require options with `getKey`.
              ; _i < arguments.length // Otherwise, arguments require options with `getKey`.
              ; _i++ // Otherwise, arguments require options with `getKey`.
              ) {
                  options[_i] = arguments[_i]; // Otherwise, arguments require options with `getKey`.
              }
              var _a = options[0] || {}, onSelectionChanged = _a.onSelectionChanged, getKey = _a.getKey, _b = _a.canSelectItem, canSelectItem = _b === void 0 ? function () { return true; } : _b, items = _a.items, _c = _a.selectionMode, selectionMode = _c === void 0 ? Selection_types_1.SelectionMode.multiple : _c;
              this.mode = selectionMode;
              this._getKey = getKey || defaultGetKey;
              this._changeEventSuppressionCount = 0;
              this._exemptedCount = 0;
              this._anchoredIndex = 0;
              this._unselectableCount = 0;
              this._onSelectionChanged = onSelectionChanged;
              this._canSelectItem = canSelectItem;
              this._isModal = false;
              this.setItems(items || [], true);
              this.count = this.getSelectedCount();
          }
          Selection.prototype.canSelectItem = function (item, index) {
              if (typeof index === 'number' && index < 0) {
                  return false;
              }
              return this._canSelectItem(item, index);
          };
          Selection.prototype.getKey = function (item, index) {
              var key = this._getKey(item, index);
              return typeof key === 'number' || key ? "" + key : '';
          };
          Selection.prototype.setChangeEvents = function (isEnabled, suppressChange) {
              this._changeEventSuppressionCount += isEnabled ? -1 : 1;
              if (this._changeEventSuppressionCount === 0 && this._hasChanged) {
                  this._hasChanged = false;
                  if (!suppressChange) {
                      this._change();
                  }
              }
          };
          Selection.prototype.isModal = function () {
              return this._isModal;
          };
          Selection.prototype.setModal = function (isModal) {
              if (this._isModal !== isModal) {
                  this.setChangeEvents(false);
                  this._isModal = isModal;
                  if (!isModal) {
                      this.setAllSelected(false);
                  }
                  this._change();
                  this.setChangeEvents(true);
              }
          };
          /**
           * Selection needs the items, call this method to set them. If the set
           * of items is the same, this will re-evaluate selection and index maps.
           * Otherwise, shouldClear should be set to true, so that selection is
           * cleared.
           */
          Selection.prototype.setItems = function (items, shouldClear) {
              if (shouldClear === void 0) { shouldClear = true; }
              var newKeyToIndexMap = {};
              var newUnselectableIndices = {};
              var hasSelectionChanged = false;
              this.setChangeEvents(false);
              // Reset the unselectable count.
              this._unselectableCount = 0;
              // Build lookup table for quick selection evaluation.
              for (var i = 0; i < items.length; i++) {
                  var item = items[i];
                  if (item) {
                      var key = this.getKey(item, i);
                      if (key) {
                          newKeyToIndexMap[key] = i;
                      }
                  }
                  newUnselectableIndices[i] = item && !this.canSelectItem(item);
                  if (newUnselectableIndices[i]) {
                      this._unselectableCount++;
                  }
              }
              if (shouldClear || items.length === 0) {
                  this._setAllSelected(false, true);
              }
              // Check the exemption list for discrepencies.
              var newExemptedIndicies = {};
              var newExemptedCount = 0;
              for (var indexProperty in this._exemptedIndices) {
                  if (this._exemptedIndices.hasOwnProperty(indexProperty)) {
                      var index = Number(indexProperty);
                      var item = this._items[index];
                      var exemptKey = item ? this.getKey(item, Number(index)) : undefined;
                      var newIndex = exemptKey ? newKeyToIndexMap[exemptKey] : index;
                      if (newIndex === undefined) {
                          // The item has likely been replaced or removed.
                          hasSelectionChanged = true;
                      }
                      else {
                          // We know the new index of the item. update the existing exemption table.
                          newExemptedIndicies[newIndex] = true;
                          newExemptedCount++;
                          hasSelectionChanged = hasSelectionChanged || newIndex !== index;
                      }
                  }
              }
              if (this._items && this._exemptedCount === 0 && items.length !== this._items.length && this._isAllSelected) {
                  // If everything was selected but the number of items has changed, selection has changed.
                  hasSelectionChanged = true;
              }
              this._exemptedIndices = newExemptedIndicies;
              this._exemptedCount = newExemptedCount;
              this._keyToIndexMap = newKeyToIndexMap;
              this._unselectableIndices = newUnselectableIndices;
              this._items = items;
              this._selectedItems = null;
              if (hasSelectionChanged) {
                  this._updateCount();
                  this._change();
              }
              this.setChangeEvents(true);
          };
          Selection.prototype.getItems = function () {
              return this._items;
          };
          Selection.prototype.getSelection = function () {
              if (!this._selectedItems) {
                  this._selectedItems = [];
                  var items = this._items;
                  if (items) {
                      for (var i = 0; i < items.length; i++) {
                          if (this.isIndexSelected(i)) {
                              this._selectedItems.push(items[i]);
                          }
                      }
                  }
              }
              return this._selectedItems;
          };
          Selection.prototype.getSelectedCount = function () {
              return this._isAllSelected
                  ? this._items.length - this._exemptedCount - this._unselectableCount
                  : this._exemptedCount;
          };
          Selection.prototype.getSelectedIndices = function () {
              if (!this._selectedIndices) {
                  this._selectedIndices = [];
                  var items = this._items;
                  if (items) {
                      for (var i = 0; i < items.length; i++) {
                          if (this.isIndexSelected(i)) {
                              this._selectedIndices.push(i);
                          }
                      }
                  }
              }
              return this._selectedIndices;
          };
          Selection.prototype.isRangeSelected = function (fromIndex, count) {
              if (count === 0) {
                  return false;
              }
              var endIndex = fromIndex + count;
              for (var i = fromIndex; i < endIndex; i++) {
                  if (!this.isIndexSelected(i)) {
                      return false;
                  }
              }
              return true;
          };
          Selection.prototype.isAllSelected = function () {
              var selectableCount = this._items.length - this._unselectableCount;
              // In single mode, we can only have a max of 1 item.
              if (this.mode === Selection_types_1.SelectionMode.single) {
                  selectableCount = Math.min(selectableCount, 1);
              }
              return ((this.count > 0 && this._isAllSelected && this._exemptedCount === 0) ||
                  (!this._isAllSelected && this._exemptedCount === selectableCount && selectableCount > 0));
          };
          Selection.prototype.isKeySelected = function (key) {
              var index = this._keyToIndexMap[key];
              return this.isIndexSelected(index);
          };
          Selection.prototype.isIndexSelected = function (index) {
              return !!((this.count > 0 && this._isAllSelected && !this._exemptedIndices[index] && !this._unselectableIndices[index]) ||
                  (!this._isAllSelected && this._exemptedIndices[index]));
          };
          Selection.prototype.setAllSelected = function (isAllSelected) {
              if (isAllSelected && this.mode !== Selection_types_1.SelectionMode.multiple) {
                  return;
              }
              var selectableCount = this._items ? this._items.length - this._unselectableCount : 0;
              this.setChangeEvents(false);
              if (selectableCount > 0 && (this._exemptedCount > 0 || isAllSelected !== this._isAllSelected)) {
                  this._exemptedIndices = {};
                  if (isAllSelected !== this._isAllSelected || this._exemptedCount > 0) {
                      this._exemptedCount = 0;
                      this._isAllSelected = isAllSelected;
                      this._change();
                  }
                  this._updateCount();
              }
              this.setChangeEvents(true);
          };
          Selection.prototype.setKeySelected = function (key, isSelected, shouldAnchor) {
              var index = this._keyToIndexMap[key];
              if (index >= 0) {
                  this.setIndexSelected(index, isSelected, shouldAnchor);
              }
          };
          Selection.prototype.setIndexSelected = function (index, isSelected, shouldAnchor) {
              if (this.mode === Selection_types_1.SelectionMode.none) {
                  return;
              }
              // Clamp the index.
              index = Math.min(Math.max(0, index), this._items.length - 1);
              // No-op on out of bounds selections.
              if (index < 0 || index >= this._items.length) {
                  return;
              }
              this.setChangeEvents(false);
              var isExempt = this._exemptedIndices[index];
              var canSelect = !this._unselectableIndices[index];
              if (canSelect) {
                  if (isSelected && this.mode === Selection_types_1.SelectionMode.single) {
                      // If this is single-select, the previous selection should be removed.
                      this._setAllSelected(false, true);
                  }
                  // Determine if we need to remove the exemption.
                  if (isExempt && ((isSelected && this._isAllSelected) || (!isSelected && !this._isAllSelected))) {
                      delete this._exemptedIndices[index];
                      this._exemptedCount--;
                  }
                  // Determine if we need to add the exemption.
                  if (!isExempt && ((isSelected && !this._isAllSelected) || (!isSelected && this._isAllSelected))) {
                      this._exemptedIndices[index] = true;
                      this._exemptedCount++;
                  }
                  if (shouldAnchor) {
                      this._anchoredIndex = index;
                  }
              }
              this._updateCount();
              this.setChangeEvents(true);
          };
          Selection.prototype.selectToKey = function (key, clearSelection) {
              this.selectToIndex(this._keyToIndexMap[key], clearSelection);
          };
          Selection.prototype.selectToIndex = function (index, clearSelection) {
              if (this.mode === Selection_types_1.SelectionMode.none) {
                  return;
              }
              if (this.mode === Selection_types_1.SelectionMode.single) {
                  this.setIndexSelected(index, true, true);
                  return;
              }
              var anchorIndex = this._anchoredIndex || 0;
              var startIndex = Math.min(index, anchorIndex);
              var endIndex = Math.max(index, anchorIndex);
              this.setChangeEvents(false);
              if (clearSelection) {
                  this._setAllSelected(false, true);
              }
              for (; startIndex <= endIndex; startIndex++) {
                  this.setIndexSelected(startIndex, true, false);
              }
              this.setChangeEvents(true);
          };
          Selection.prototype.toggleAllSelected = function () {
              this.setAllSelected(!this.isAllSelected());
          };
          Selection.prototype.toggleKeySelected = function (key) {
              this.setKeySelected(key, !this.isKeySelected(key), true);
          };
          Selection.prototype.toggleIndexSelected = function (index) {
              this.setIndexSelected(index, !this.isIndexSelected(index), true);
          };
          Selection.prototype.toggleRangeSelected = function (fromIndex, count) {
              if (this.mode === Selection_types_1.SelectionMode.none) {
                  return;
              }
              var isRangeSelected = this.isRangeSelected(fromIndex, count);
              var endIndex = fromIndex + count;
              if (this.mode === Selection_types_1.SelectionMode.single && count > 1) {
                  return;
              }
              this.setChangeEvents(false);
              for (var i = fromIndex; i < endIndex; i++) {
                  this.setIndexSelected(i, !isRangeSelected, false);
              }
              this.setChangeEvents(true);
          };
          Selection.prototype._updateCount = function (preserveModalState) {
              if (preserveModalState === void 0) { preserveModalState = false; }
              var count = this.getSelectedCount();
              if (count !== this.count) {
                  this.count = count;
                  this._change();
              }
              if (!this.count && !preserveModalState) {
                  this.setModal(false);
              }
          };
          Selection.prototype._setAllSelected = function (isAllSelected, preserveModalState) {
              if (preserveModalState === void 0) { preserveModalState = false; }
              if (isAllSelected && this.mode !== Selection_types_1.SelectionMode.multiple) {
                  return;
              }
              var selectableCount = this._items ? this._items.length - this._unselectableCount : 0;
              this.setChangeEvents(false);
              if (selectableCount > 0 && (this._exemptedCount > 0 || isAllSelected !== this._isAllSelected)) {
                  this._exemptedIndices = {};
                  if (isAllSelected !== this._isAllSelected || this._exemptedCount > 0) {
                      this._exemptedCount = 0;
                      this._isAllSelected = isAllSelected;
                      this._change();
                  }
                  this._updateCount(preserveModalState);
              }
              this.setChangeEvents(true);
          };
          Selection.prototype._change = function () {
              if (this._changeEventSuppressionCount === 0) {
                  this._selectedItems = null;
                  this._selectedIndices = undefined;
                  EventGroup_1.EventGroup.raise(this, Selection_types_1.SELECTION_CHANGE);
                  if (this._onSelectionChanged) {
                      this._onSelectionChanged();
                  }
              }
              else {
                  this._hasChanged = true;
              }
          };
          return Selection;
      }());
      exports.Selection = Selection;
      function defaultGetKey(item, index) {
          // 0 may be used as a key
          var _a = (item || {}).key, key = _a === void 0 ? "" + index : _a;
          return key;
      }
  });
  //# sourceMappingURL=Selection.js.map