"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.useTreeViewItems = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var React = _interopRequireWildcard(require("react"));
var _publishTreeViewEvent = require("../../utils/publishTreeViewEvent");
var _useTreeViewItems = require("./useTreeViewItems.utils");
var _TreeViewItemDepthContext = require("../../TreeViewItemDepthContext");
var _useTreeViewId = require("../../corePlugins/useTreeViewId/useTreeViewId.utils");
var _jsxRuntime = require("react/jsx-runtime");
const _excluded = ["children"];
const updateItemsState = ({
  items,
  isItemDisabled,
  getItemLabel,
  getItemId
}) => {
  const itemMetaMap = {};
  const itemMap = {};
  const itemOrderedChildrenIds = {
    [_useTreeViewItems.TREE_VIEW_ROOT_PARENT_ID]: []
  };
  const processItem = (item, depth, parentId) => {
    const id = getItemId ? getItemId(item) : item.id;
    if (id == null) {
      throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', 'An item was provided without id in the `items` prop:', JSON.stringify(item)].join('\n'));
    }
    if (itemMetaMap[id] != null) {
      throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', `Two items were provided with the same id in the \`items\` prop: "${id}"`].join('\n'));
    }
    const label = getItemLabel ? getItemLabel(item) : item.label;
    if (label == null) {
      throw new Error(['MUI X: The Tree View component requires all items to have a `label` property.', 'Alternatively, you can use the `getItemLabel` prop to specify a custom label for each item.', 'An item was provided without label in the `items` prop:', JSON.stringify(item)].join('\n'));
    }
    itemMetaMap[id] = {
      id,
      label,
      parentId,
      idAttribute: undefined,
      expandable: !!item.children?.length,
      disabled: isItemDisabled ? isItemDisabled(item) : false,
      depth
    };
    itemMap[id] = item;
    const parentIdWithDefault = parentId ?? _useTreeViewItems.TREE_VIEW_ROOT_PARENT_ID;
    if (!itemOrderedChildrenIds[parentIdWithDefault]) {
      itemOrderedChildrenIds[parentIdWithDefault] = [];
    }
    itemOrderedChildrenIds[parentIdWithDefault].push(id);
    item.children?.forEach(child => processItem(child, depth + 1, id));
  };
  items.forEach(item => processItem(item, 0, null));
  const itemChildrenIndexes = {};
  Object.keys(itemOrderedChildrenIds).forEach(parentId => {
    itemChildrenIndexes[parentId] = (0, _useTreeViewItems.buildSiblingIndexes)(itemOrderedChildrenIds[parentId]);
  });
  return {
    itemMetaMap,
    itemMap,
    itemOrderedChildrenIds,
    itemChildrenIndexes
  };
};
const useTreeViewItems = ({
  instance,
  params,
  state,
  setState,
  experimentalFeatures
}) => {
  const getItemMeta = React.useCallback(itemId => state.items.itemMetaMap[itemId], [state.items.itemMetaMap]);
  const getItem = React.useCallback(itemId => state.items.itemMap[itemId], [state.items.itemMap]);
  const getItemTree = React.useCallback(() => {
    const getItemFromItemId = id => {
      const _state$items$itemMap$ = state.items.itemMap[id],
        item = (0, _objectWithoutPropertiesLoose2.default)(_state$items$itemMap$, _excluded);
      const newChildren = state.items.itemOrderedChildrenIds[id];
      if (newChildren) {
        item.children = newChildren.map(getItemFromItemId);
      }
      return item;
    };
    return state.items.itemOrderedChildrenIds[_useTreeViewItems.TREE_VIEW_ROOT_PARENT_ID].map(getItemFromItemId);
  }, [state.items.itemMap, state.items.itemOrderedChildrenIds]);
  const isItemDisabled = React.useCallback(itemId => {
    if (itemId == null) {
      return false;
    }
    let itemMeta = instance.getItemMeta(itemId);

    // This can be called before the item has been added to the item map.
    if (!itemMeta) {
      return false;
    }
    if (itemMeta.disabled) {
      return true;
    }
    while (itemMeta.parentId != null) {
      itemMeta = instance.getItemMeta(itemMeta.parentId);
      if (itemMeta.disabled) {
        return true;
      }
    }
    return false;
  }, [instance]);
  const getItemIndex = React.useCallback(itemId => {
    const parentId = instance.getItemMeta(itemId).parentId ?? _useTreeViewItems.TREE_VIEW_ROOT_PARENT_ID;
    return state.items.itemChildrenIndexes[parentId][itemId];
  }, [instance, state.items.itemChildrenIndexes]);
  const getItemOrderedChildrenIds = React.useCallback(itemId => state.items.itemOrderedChildrenIds[itemId ?? _useTreeViewItems.TREE_VIEW_ROOT_PARENT_ID] ?? [], [state.items.itemOrderedChildrenIds]);
  const getItemDOMElement = itemId => {
    const itemMeta = instance.getItemMeta(itemId);
    if (itemMeta == null) {
      return null;
    }
    return document.getElementById((0, _useTreeViewId.generateTreeItemIdAttribute)({
      treeId: state.id.treeId,
      itemId,
      id: itemMeta.idAttribute
    }));
  };
  const isItemNavigable = itemId => {
    if (params.disabledItemsFocusable) {
      return true;
    }
    return !instance.isItemDisabled(itemId);
  };
  const areItemUpdatesPreventedRef = React.useRef(false);
  const preventItemUpdates = React.useCallback(() => {
    areItemUpdatesPreventedRef.current = true;
  }, []);
  const areItemUpdatesPrevented = React.useCallback(() => areItemUpdatesPreventedRef.current, []);
  React.useEffect(() => {
    if (instance.areItemUpdatesPrevented()) {
      return;
    }
    setState(prevState => {
      const newState = updateItemsState({
        items: params.items,
        isItemDisabled: params.isItemDisabled,
        getItemId: params.getItemId,
        getItemLabel: params.getItemLabel
      });
      Object.values(prevState.items.itemMetaMap).forEach(item => {
        if (!newState.itemMetaMap[item.id]) {
          (0, _publishTreeViewEvent.publishTreeViewEvent)(instance, 'removeItem', {
            id: item.id
          });
        }
      });
      return (0, _extends2.default)({}, prevState, {
        items: newState
      });
    });
  }, [instance, setState, params.items, params.isItemDisabled, params.getItemId, params.getItemLabel]);
  const getItemsToRender = () => {
    const getPropsFromItemId = id => {
      const item = state.items.itemMetaMap[id];
      return {
        label: item.label,
        itemId: item.id,
        id: item.idAttribute,
        children: state.items.itemOrderedChildrenIds[id]?.map(getPropsFromItemId)
      };
    };
    return state.items.itemOrderedChildrenIds[_useTreeViewItems.TREE_VIEW_ROOT_PARENT_ID].map(getPropsFromItemId);
  };
  return {
    getRootProps: () => ({
      style: {
        '--TreeView-itemChildrenIndentation': typeof params.itemChildrenIndentation === 'number' ? `${params.itemChildrenIndentation}px` : params.itemChildrenIndentation
      }
    }),
    publicAPI: {
      getItem,
      getItemDOMElement,
      getItemTree,
      getItemOrderedChildrenIds
    },
    instance: {
      getItemMeta,
      getItem,
      getItemTree,
      getItemsToRender,
      getItemIndex,
      getItemDOMElement,
      getItemOrderedChildrenIds,
      isItemDisabled,
      isItemNavigable,
      preventItemUpdates,
      areItemUpdatesPrevented
    },
    contextValue: {
      items: {
        onItemClick: params.onItemClick,
        disabledItemsFocusable: params.disabledItemsFocusable,
        indentationAtItemLevel: experimentalFeatures.indentationAtItemLevel ?? false
      }
    }
  };
};
exports.useTreeViewItems = useTreeViewItems;
useTreeViewItems.getInitialState = params => ({
  items: updateItemsState({
    items: params.items,
    isItemDisabled: params.isItemDisabled,
    getItemId: params.getItemId,
    getItemLabel: params.getItemLabel
  })
});
useTreeViewItems.getDefaultizedParams = ({
  params
}) => (0, _extends2.default)({}, params, {
  disabledItemsFocusable: params.disabledItemsFocusable ?? false,
  itemChildrenIndentation: params.itemChildrenIndentation ?? '12px'
});
useTreeViewItems.wrapRoot = ({
  children,
  instance
}) => {
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_TreeViewItemDepthContext.TreeViewItemDepthContext.Provider, {
    value: itemId => instance.getItemMeta(itemId)?.depth ?? 0,
    children: children
  });
};
useTreeViewItems.params = {
  disabledItemsFocusable: true,
  items: true,
  isItemDisabled: true,
  getItemLabel: true,
  getItemId: true,
  onItemClick: true,
  itemChildrenIndentation: true
};