"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Backstage
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.BackstageComposer = exports.useGroupedItems = void 0;
const React = require("react");
const appui_abstract_1 = require("@itwin/appui-abstract");
const appui_layout_react_1 = require("@itwin/appui-layout-react");
const SafeAreaContext_1 = require("../safearea/SafeAreaContext");
const SyncUiEventDispatcher_1 = require("../syncui/SyncUiEventDispatcher");
const BackstageComposerItem_1 = require("./BackstageComposerItem");
const BackstageManager_1 = require("./BackstageManager");
const useDefaultBackstageItems_1 = require("./useDefaultBackstageItems");
const useUiItemsProviderBackstageItems_1 = require("./useUiItemsProviderBackstageItems");
// cSpell:ignore safearea
/* eslint-disable deprecation/deprecation */
/** Private function to set up sync event monitoring of backstage items */
function useBackstageItemSyncEffect(itemsManager, syncIdsOfInterest) {
    const isInitialMount = React.useRef(true);
    React.useEffect(() => {
        const handleSyncUiEvent = (args) => {
            if (0 === syncIdsOfInterest.length)
                return;
            // istanbul ignore else
            if (syncIdsOfInterest.some((value) => args.eventIds.has(value.toLowerCase()))) {
                // process each item that has interest
                itemsManager.refreshAffectedItems(args.eventIds);
            }
        };
        if (isInitialMount.current) {
            isInitialMount.current = false;
            // initialize the display state of any items with syncIds/condition defined
            itemsManager.refreshAffectedItems(new Set(syncIdsOfInterest));
        }
        SyncUiEventDispatcher_1.SyncUiEventDispatcher.onSyncUiEvent.addListener(handleSyncUiEvent);
        return () => {
            SyncUiEventDispatcher_1.SyncUiEventDispatcher.onSyncUiEvent.removeListener(handleSyncUiEvent);
        };
    }, [itemsManager, itemsManager.items, syncIdsOfInterest]);
}
/** local function to combine items from Stage and from Extensions */
function combineItems(stageItems, addonItems, hideSoloStageEntry) {
    let items = [];
    if (stageItems.length) {
        // Walk through each and ensure no duplicate ids are added.
        stageItems.forEach((srcItem) => {
            if (-1 === items.findIndex((item) => item.id === srcItem.id)) {
                items.push(srcItem);
            }
        });
    }
    if (addonItems.length) {
        // Walk through each and ensure no duplicate ids are added.
        addonItems.forEach((srcItem) => {
            if (-1 === items.findIndex((item) => item.id === srcItem.id)) {
                items.push(srcItem);
            }
        });
    }
    if (hideSoloStageEntry) {
        // per user request don't show stage launcher if only one stage is available
        const numberOfFrontstageItems = items.reduce((accumulator, item) => accumulator + ((0, appui_abstract_1.isStageLauncher)(item) ? 1 : 0), 0);
        if (1 === numberOfFrontstageItems)
            items = items.filter((item) => !(0, appui_abstract_1.isStageLauncher)(item));
    }
    return items;
}
/** @internal */
const useGroupedItems = (items) => {
    return React.useMemo(() => {
        const grouped = items.reduce((acc, item) => {
            if (appui_abstract_1.ConditionalBooleanValue.getValue(item.isHidden))
                return acc;
            const groupIndex = acc.findIndex((group) => group[0].groupPriority === item.groupPriority);
            if (groupIndex >= 0)
                return [
                    ...acc.slice(0, groupIndex),
                    [
                        ...acc[groupIndex],
                        item,
                    ],
                    ...acc.slice(groupIndex + 1),
                ];
            return [
                ...acc,
                [
                    item,
                ],
            ];
        }, []);
        const sortedGroups = grouped.reduce((acc, group) => {
            const sortedGroup = [...group].sort((a, b) => a.itemPriority - b.itemPriority);
            return [
                ...acc,
                sortedGroup,
            ];
        }, []);
        return [...sortedGroups].sort((a, b) => a[0].groupPriority - b[0].groupPriority);
    }, [items]);
};
exports.useGroupedItems = useGroupedItems;
/** Backstage component composed from [[BackstageManager]] items.
 * @public
 */
function BackstageComposer(props) {
    const [defaultItemsManager, setDefaultItemsManager] = React.useState(new appui_abstract_1.BackstageItemsManager(props.items));
    const initialItems = React.useRef(props.items);
    React.useEffect(() => {
        if (initialItems.current !== props.items) {
            initialItems.current = props.items;
            setDefaultItemsManager(new appui_abstract_1.BackstageItemsManager(props.items));
        }
    }, [props.items]);
    const manager = (0, BackstageManager_1.useBackstageManager)();
    const isOpen = (0, BackstageManager_1.useIsBackstageOpen)(manager);
    const safeAreaInsets = React.useContext(SafeAreaContext_1.SafeAreaContext);
    const handleClose = React.useCallback(() => {
        manager.close();
    }, [manager]);
    const defaultItems = (0, useDefaultBackstageItems_1.useDefaultBackstageItems)(defaultItemsManager);
    const syncIdsOfInterest = React.useMemo(() => appui_abstract_1.BackstageItemsManager.getSyncIdsOfInterest(defaultItems), [defaultItems]);
    useBackstageItemSyncEffect(defaultItemsManager, syncIdsOfInterest);
    const [addonItemsManager] = React.useState(new appui_abstract_1.BackstageItemsManager());
    const addonItems = (0, useUiItemsProviderBackstageItems_1.useUiItemsProviderBackstageItems)(addonItemsManager);
    const addonSyncIdsOfInterest = React.useMemo(() => appui_abstract_1.BackstageItemsManager.getSyncIdsOfInterest(addonItems), [addonItems]);
    useBackstageItemSyncEffect(addonItemsManager, addonSyncIdsOfInterest);
    const combinedBackstageItems = React.useMemo(() => combineItems(defaultItems, addonItems, !!props.hideSoloStageEntry), [defaultItems, addonItems, props.hideSoloStageEntry]);
    const groups = (0, exports.useGroupedItems)(combinedBackstageItems);
    return (React.createElement(appui_layout_react_1.Backstage, { className: props.className, header: props.header, isOpen: isOpen, onClose: handleClose, safeAreaInsets: safeAreaInsets, showOverlay: props.showOverlay, style: props.style }, groups.map((group, groupIndex) => (group.map((item, itemIndex) => {
        const composerItem = (React.createElement(BackstageComposerItem_1.BackstageComposerItem, { item: item, key: item.id }));
        return itemIndex === 0 && groupIndex > 0 ? (React.createElement(React.Fragment, { key: groupIndex },
            React.createElement(appui_layout_react_1.BackstageSeparator, null),
            composerItem)) : composerItem;
    })))));
}
exports.BackstageComposer = BackstageComposer;
//# sourceMappingURL=BackstageComposer.js.map