"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 Toolbar
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.ToolbarComposer = void 0;
const React = require("react");
const components_react_1 = require("@itwin/components-react");
const core_bentley_1 = require("@itwin/core-bentley");
const core_react_1 = require("@itwin/core-react");
const UiFramework_1 = require("../UiFramework");
const DragInteraction_1 = require("./DragInteraction");
const ToolbarItem_1 = require("./ToolbarItem");
const Toolbar_1 = require("./Toolbar");
const useActiveToolIdSynchedItems_1 = require("./useActiveToolIdSynchedItems");
const useActiveStageProvidedToolbarItems_1 = require("./useActiveStageProvidedToolbarItems");
function addItemToSpecifiedParentGroup(items, groupChildren) {
    const outItems = [];
    for (const toolbarItem of items) {
        if (!(0, ToolbarItem_1.isToolbarGroupItem)(toolbarItem)) {
            outItems.push(toolbarItem);
            continue;
        }
        const newChildren = addItemToSpecifiedParentGroup(toolbarItem.items, groupChildren);
        const foundIndices = [];
        groupChildren.forEach((entry, index) => {
            if (entry.parentGroupItemId === toolbarItem.id) {
                foundIndices.push(index);
            }
        });
        if (foundIndices.length) {
            // process in reverse order so groupChildren can be reduced as we find matches
            foundIndices
                .sort((a, b) => a - b)
                .reverse()
                .forEach((foundIndex) => {
                newChildren.push(groupChildren[foundIndex]);
                groupChildren.splice(foundIndex);
            });
        }
        outItems.push({ ...toolbarItem, items: newChildren });
    }
    return outItems;
}
function cloneGroup(inGroup) {
    const childItems = [];
    inGroup.items.forEach((item) => {
        if ((0, ToolbarItem_1.isToolbarGroupItem)(item))
            childItems.push(cloneGroup(item));
        else
            childItems.push(item);
    });
    const clonedGroup = { ...inGroup, items: childItems };
    return clonedGroup;
}
function getItemSortValue(item) {
    const groupValue = undefined === item.groupPriority ? 0 : item.groupPriority;
    return groupValue * 10000 + item.itemPriority;
}
function sortItems(items) {
    return [...items]
        .sort((a, b) => getItemSortValue(a) - getItemSortValue(b))
        .map((i) => {
        if ((0, ToolbarItem_1.isToolbarGroupItem)(i)) {
            return { ...i, items: sortItems(i.items) };
        }
        return i;
    });
}
/**
 * Create a forEach handler that will add every element of an array of ToolbarItems
 * to a list of items that can then be replaced in its proper place, ensuring that
 * the same item, from different list, is not added multiple times.
 * @param items Output list of items
 * @param groupChildren Output list of group children to redistribute.
 * @returns Array<ToolbarItem>.forEach handler.
 */
function addIfNotDuplicate(items, groupChildren) {
    return (srcItem) => {
        if (-1 === items.findIndex((item) => item.id === srcItem.id)) {
            // if the default item is a group that an addon may insert into copy it so we don't mess with original
            const toolbarItem = (0, ToolbarItem_1.isToolbarGroupItem)(srcItem)
                ? cloneGroup(srcItem)
                : srcItem;
            if (((0, ToolbarItem_1.isToolbarGroupItem)(toolbarItem) || (0, ToolbarItem_1.isToolbarActionItem)(toolbarItem)) &&
                toolbarItem.parentGroupItemId)
                groupChildren.push(toolbarItem);
            else
                items.push(toolbarItem);
        }
    };
}
/** local function to combine items from Stage and from Extensions */
function combineItems(defaultItems, addonItems) {
    let items = [];
    const groupChildren = [];
    defaultItems.forEach(addIfNotDuplicate(items, groupChildren));
    addonItems.forEach(addIfNotDuplicate(items, groupChildren));
    // if an item from an addon has specified a parent group then try to find it and insert it.  If no parent is found, add item at root level.
    if (groupChildren.length) {
        items = addItemToSpecifiedParentGroup(items, groupChildren);
        groupChildren.forEach((toolbarItem) => {
            core_bentley_1.Logger.logWarning("ToolbarComposer", `Requested Parent Group [${toolbarItem.parentGroupItemId}] not found, so item [${toolbarItem.id}] is added directly to toolbar.`);
            items.push(toolbarItem);
        });
    }
    return sortItems(items);
}
const useProximityOpacitySetting = () => {
    const [proximityOpacity, setProximityOpacity] = React.useState(UiFramework_1.UiFramework.visibility.useProximityOpacity // eslint-disable-line deprecation/deprecation
    );
    React.useEffect(() => {
        UiFramework_1.UiFramework.onUiVisibilityChanged.addListener(() => setProximityOpacity(UiFramework_1.UiFramework.visibility.useProximityOpacity) // eslint-disable-line deprecation/deprecation
        );
    }, []);
    return proximityOpacity;
};
const useSnapWidgetOpacitySetting = () => {
    const [snapWidgetOpacity, setSnapWidgetOpacity] = React.useState(UiFramework_1.UiFramework.visibility.snapWidgetOpacity);
    React.useEffect(() => {
        UiFramework_1.UiFramework.onUiVisibilityChanged.addListener(() => setSnapWidgetOpacity(UiFramework_1.UiFramework.visibility.snapWidgetOpacity));
    }, []);
    return snapWidgetOpacity;
};
/**
 * Toolbar that is populated and maintained by UI item providers.
 * @note Overrides `isActive` property based on the active tool id.
 * @public
 */
function ToolbarComposer(props) {
    const { usage, orientation } = props;
    // process items from addon UI providers
    const addonItems = (0, useActiveStageProvidedToolbarItems_1.useActiveStageProvidedToolbarItems)(usage, orientation);
    const allItems = React.useMemo(() => {
        return combineItems(props.items, addonItems);
    }, [props.items, addonItems]);
    const items = (0, useActiveToolIdSynchedItems_1.useActiveToolIdSynchedItems)(allItems, UiFramework_1.UiFramework.frontstages);
    const toolbarOrientation = orientation === ToolbarItem_1.ToolbarOrientation.Horizontal
        ? core_react_1.Orientation.Horizontal
        : core_react_1.Orientation.Vertical;
    const expandsTo = toolbarOrientation === core_react_1.Orientation.Horizontal
        ? components_react_1.Direction.Bottom
        : usage === ToolbarItem_1.ToolbarUsage.ViewNavigation
            ? components_react_1.Direction.Left
            : components_react_1.Direction.Right;
    const panelAlignment = toolbarOrientation === core_react_1.Orientation.Horizontal &&
        usage === ToolbarItem_1.ToolbarUsage.ViewNavigation
        ? components_react_1.ToolbarPanelAlignment.End
        : components_react_1.ToolbarPanelAlignment.Start;
    const isDragEnabled = React.useContext(DragInteraction_1.ToolbarDragInteractionContext);
    const useProximityOpacity = useProximityOpacitySetting();
    const snapWidgetOpacity = useSnapWidgetOpacitySetting();
    return (React.createElement(Toolbar_1.Toolbar, { enableOverflow: true, expandsTo: expandsTo, panelAlignment: panelAlignment, items: items, useDragInteraction: isDragEnabled, toolbarOpacitySetting: (useProximityOpacity || snapWidgetOpacity) &&
            !core_bentley_1.ProcessDetector.isMobileBrowser
            ? components_react_1.ToolbarOpacitySetting.Proximity
            : components_react_1.ToolbarOpacitySetting.Defaults }));
}
exports.ToolbarComposer = ToolbarComposer;
//# sourceMappingURL=ToolbarComposer.js.map