"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.useTreeViewSelection = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _tree = require("../../utils/tree");
var _useTreeViewSelection = require("./useTreeViewSelection.utils");
const useTreeViewSelection = ({
  instance,
  params,
  models
}) => {
  const lastSelectedItem = React.useRef(null);
  const lastSelectedRange = React.useRef({});
  const selectedItemsMap = React.useMemo(() => {
    const temp = new Map();
    if (Array.isArray(models.selectedItems.value)) {
      models.selectedItems.value.forEach(id => {
        temp.set(id, true);
      });
    } else if (models.selectedItems.value != null) {
      temp.set(models.selectedItems.value, true);
    }
    return temp;
  }, [models.selectedItems.value]);
  const setSelectedItems = (event, newSelectedItems) => {
    if (params.onItemSelectionToggle) {
      if (params.multiSelect) {
        const addedItems = newSelectedItems.filter(itemId => !instance.isItemSelected(itemId));
        const removedItems = models.selectedItems.value.filter(itemId => !newSelectedItems.includes(itemId));
        addedItems.forEach(itemId => {
          params.onItemSelectionToggle(event, itemId, true);
        });
        removedItems.forEach(itemId => {
          params.onItemSelectionToggle(event, itemId, false);
        });
      } else if (newSelectedItems !== models.selectedItems.value) {
        if (models.selectedItems.value != null) {
          params.onItemSelectionToggle(event, models.selectedItems.value, false);
        }
        if (newSelectedItems != null) {
          params.onItemSelectionToggle(event, newSelectedItems, true);
        }
      }
    }
    if (params.onSelectedItemsChange) {
      params.onSelectedItemsChange(event, newSelectedItems);
    }
    models.selectedItems.setControlledValue(newSelectedItems);
  };
  const isItemSelected = itemId => selectedItemsMap.has(itemId);
  const selectItem = ({
    event,
    itemId,
    keepExistingSelection = false,
    shouldBeSelected
  }) => {
    if (params.disableSelection) {
      return;
    }
    let newSelected;
    if (keepExistingSelection) {
      const cleanSelectedItems = (0, _useTreeViewSelection.convertSelectedItemsToArray)(models.selectedItems.value);
      const isSelectedBefore = instance.isItemSelected(itemId);
      if (isSelectedBefore && (shouldBeSelected === false || shouldBeSelected == null)) {
        newSelected = cleanSelectedItems.filter(id => id !== itemId);
      } else if (!isSelectedBefore && (shouldBeSelected === true || shouldBeSelected == null)) {
        newSelected = [itemId].concat(cleanSelectedItems);
      } else {
        newSelected = cleanSelectedItems;
      }
    } else {
      // eslint-disable-next-line no-lonely-if
      if (shouldBeSelected === false || shouldBeSelected == null && instance.isItemSelected(itemId)) {
        newSelected = params.multiSelect ? [] : null;
      } else {
        newSelected = params.multiSelect ? [itemId] : itemId;
      }
    }
    setSelectedItems(event, newSelected);
    lastSelectedItem.current = itemId;
    lastSelectedRange.current = {};
  };
  const selectRange = (event, [start, end]) => {
    if (params.disableSelection || !params.multiSelect) {
      return;
    }
    let newSelectedItems = (0, _useTreeViewSelection.convertSelectedItemsToArray)(models.selectedItems.value).slice();

    // If the last selection was a range selection,
    // remove the items that were part of the last range from the model
    if (Object.keys(lastSelectedRange.current).length > 0) {
      newSelectedItems = newSelectedItems.filter(id => !lastSelectedRange.current[id]);
    }

    // Add to the model the items that are part of the new range and not already part of the model.
    const selectedItemsLookup = (0, _useTreeViewSelection.getLookupFromArray)(newSelectedItems);
    const range = (0, _tree.getNonDisabledItemsInRange)(instance, start, end);
    const itemsToAddToModel = range.filter(id => !selectedItemsLookup[id]);
    newSelectedItems = newSelectedItems.concat(itemsToAddToModel);
    setSelectedItems(event, newSelectedItems);
    lastSelectedRange.current = (0, _useTreeViewSelection.getLookupFromArray)(range);
  };
  const expandSelectionRange = (event, itemId) => {
    if (lastSelectedItem.current != null) {
      const [start, end] = (0, _tree.findOrderInTremauxTree)(instance, itemId, lastSelectedItem.current);
      selectRange(event, [start, end]);
    }
  };
  const selectRangeFromStartToItem = (event, itemId) => {
    selectRange(event, [(0, _tree.getFirstNavigableItem)(instance), itemId]);
  };
  const selectRangeFromItemToEnd = (event, itemId) => {
    selectRange(event, [itemId, (0, _tree.getLastNavigableItem)(instance)]);
  };
  const selectAllNavigableItems = event => {
    if (params.disableSelection || !params.multiSelect) {
      return;
    }
    const navigableItems = (0, _tree.getAllNavigableItems)(instance);
    setSelectedItems(event, navigableItems);
    lastSelectedRange.current = (0, _useTreeViewSelection.getLookupFromArray)(navigableItems);
  };
  const selectItemFromArrowNavigation = (event, currentItem, nextItem) => {
    if (params.disableSelection || !params.multiSelect) {
      return;
    }
    let newSelectedItems = (0, _useTreeViewSelection.convertSelectedItemsToArray)(models.selectedItems.value).slice();
    if (Object.keys(lastSelectedRange.current).length === 0) {
      newSelectedItems.push(nextItem);
      lastSelectedRange.current = {
        [currentItem]: true,
        [nextItem]: true
      };
    } else {
      if (!lastSelectedRange.current[currentItem]) {
        lastSelectedRange.current = {};
      }
      if (lastSelectedRange.current[nextItem]) {
        newSelectedItems = newSelectedItems.filter(id => id !== currentItem);
        delete lastSelectedRange.current[currentItem];
      } else {
        newSelectedItems.push(nextItem);
        lastSelectedRange.current[nextItem] = true;
      }
    }
    setSelectedItems(event, newSelectedItems);
  };
  return {
    getRootProps: () => ({
      'aria-multiselectable': params.multiSelect
    }),
    publicAPI: {
      selectItem
    },
    instance: {
      isItemSelected,
      selectItem,
      selectAllNavigableItems,
      expandSelectionRange,
      selectRangeFromStartToItem,
      selectRangeFromItemToEnd,
      selectItemFromArrowNavigation
    },
    contextValue: {
      selection: {
        multiSelect: params.multiSelect,
        checkboxSelection: params.checkboxSelection,
        disableSelection: params.disableSelection
      }
    }
  };
};
exports.useTreeViewSelection = useTreeViewSelection;
useTreeViewSelection.models = {
  selectedItems: {
    getDefaultValue: params => params.defaultSelectedItems
  }
};
const DEFAULT_SELECTED_ITEMS = [];
useTreeViewSelection.getDefaultizedParams = ({
  params
}) => (0, _extends2.default)({}, params, {
  disableSelection: params.disableSelection ?? false,
  multiSelect: params.multiSelect ?? false,
  checkboxSelection: params.checkboxSelection ?? false,
  defaultSelectedItems: params.defaultSelectedItems ?? (params.multiSelect ? DEFAULT_SELECTED_ITEMS : null)
});
useTreeViewSelection.params = {
  disableSelection: true,
  multiSelect: true,
  checkboxSelection: true,
  defaultSelectedItems: true,
  selectedItems: true,
  onSelectedItemsChange: true,
  onItemSelectionToggle: true
};