/*---------------------------------------------------------------------------------------------
 * 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
 */
import "./ToolGroup.scss";
import classnames from "classnames";
import * as React from "react";
import { OverflowButton } from "./OverflowButton.js";
import { useOverflow } from "./useOverflow.js";
import { getChildKey } from "../../layout/tool-settings/Docked.js";
import { ToolbarContext } from "./Toolbar.js";
import { Surface } from "./Surface.js";
import { useSafeContext } from "../../hooks/useSafeContext.js";
/** @internal */
export function ToolGroup({ children, className, ...props }) {
    const { panelAlignment, orientation } = useSafeContext(ToolbarContext);
    const childrenArray = React.Children.toArray(children);
    const keyToChildMap = childrenArray.reduce((acc, child, index) => {
        const childKey = getChildKey(child, index);
        acc.set(childKey, child);
        return acc;
    }, new Map());
    const childrenKeys = Array.from(keyToChildMap.keys());
    const itemRefs = React.useRef(new Map());
    const overflowRef = React.useRef(null);
    const getItemSize = React.useCallback((item) => {
        const element = itemRefs.current.get(item);
        if (!element)
            return { width: 0, height: 0 };
        const elementSize = element.getBoundingClientRect();
        const separatorSize = getSeparatorSize(element);
        if (!separatorSize)
            return elementSize;
        return {
            width: elementSize.width + separatorSize.width,
            height: elementSize.height + separatorSize.height,
        };
    }, []);
    const getOverflowSize = React.useCallback(() => {
        const element = overflowRef.current;
        if (!element)
            return { width: 0, height: 0 };
        return element.getBoundingClientRect();
    }, []);
    const [containerRef, componentRef, visibleCount, renderOverflow] = useOverflow(childrenKeys, orientation, getItemSize, getOverflowSize);
    const keyToChildEntries = Array.from(keyToChildMap.entries());
    const visibleChildren = keyToChildEntries.slice(0, visibleCount);
    const overflown = keyToChildEntries.slice(visibleCount);
    return (React.createElement("div", { className: classnames("uifw-toolbar-group-toolGroup_container", `uifw-${orientation}`, `uifw-${panelAlignment}`, className), ref: containerRef },
        React.createElement(Surface, { orientation: orientation, ref: componentRef, ...props },
            visibleChildren.map(([item, child]) => {
                if (!React.isValidElement(child))
                    return child;
                return React.cloneElement(child, {
                    ref: (el) => {
                        if (!el) {
                            itemRefs.current.delete(item);
                            return;
                        }
                        itemRefs.current.set(item, el);
                    },
                });
            }),
            renderOverflow && (React.createElement(OverflowButton, { ref: overflowRef }, overflown.map(([_, child]) => child))))));
}
// First item in the group reserves space for the separator to correctly calculate the overflow.
function getSeparatorSize(toolbarItem) {
    const firstInGroup = isFirstInGroup(toolbarItem);
    if (!firstInGroup)
        return undefined;
    // Last group does not have a separator.
    if (isLastGroup(toolbarItem))
        return undefined;
    const separator = getSeparator(toolbarItem);
    if (!separator)
        return undefined;
    return separator.getBoundingClientRect();
}
// Returns if the toolbar item is the first in its group.
function isFirstInGroup(toolbarItem) {
    const prev = toolbarItem.previousElementSibling;
    if (prev?.tagName === "BUTTON")
        return false;
    return true;
}
// Returns if the toolbar item is in the last group of the toolbar.
function isLastGroup(toolbarItem) {
    let el = toolbarItem.nextElementSibling;
    while (el) {
        if (el.tagName === "BUTTON" && el.hasAttribute("data-item-id")) {
            return false;
        }
        el = el.nextElementSibling;
    }
    return true;
}
// Returns the first separator element after the toolbar item, if it exists.
function getSeparator(toolbarItem) {
    let el = toolbarItem.nextElementSibling;
    while (el) {
        if (el.classList.contains("uifw-toolbar-newToolbars-separator")) {
            return el;
        }
        el = el.nextElementSibling;
    }
    return undefined;
}
//# sourceMappingURL=ToolGroup.js.map