import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import Icon, { registerIcon } from '../Icon';
import * as caretDownIcon from '../Icon/icons/caret-down.icon';
import { useEscape, useFocusWithin, useI18n, useTheme } from '../../hooks';
import { createStringMatcher, isValidElement } from '../../utils';
import { isSolidColor } from '../../styles';
import { ThemeOverride } from '../Configuration';
import Popover from '../Popover';
import Menu from '../Menu';
import { StyledTopNav, StyledTopNavList, StyledTopNavMeasureRow, StyledTopNavSection, StyledTopNavUtilBar, StyledTopNavItem, StyledTopNavItemHidden, StyledTopNavUtilButton, StyledTopNavCountBadge, StyledTopNavCreateArea } from './AppTopNav.styles';
import { navContrastColors } from './style-utils';
import { CaseTypes } from './AppNavigationPanel';
import TopNavMoreMenu from './TopNavMoreMenu';
import { useTopNavOverflow } from './useTopNavOverflow';
import { AppShellDrawerContext } from './AppShellContext';
registerIcon(caretDownIcon);
const hasActiveDescendant = (link) => {
    if (link.active)
        return true;
    return link.links?.some(hasActiveDescendant) ?? false;
};
const linkToFlyoutItem = (link) => {
    const userOnClick = link.onClick;
    const children = link.links?.map(linkToFlyoutItem);
    const hasChildren = children && children.length > 0;
    return {
        id: link.id || link.name,
        primary: link.name,
        visual: link.icon ? _jsx(Icon, { name: link.icon }) : undefined,
        href: hasChildren ? undefined : link.href,
        // MenuItem uses `typeof selected !== 'boolean'` to decide expand vs click.
        selected: hasChildren ? undefined : link.active || undefined,
        onClick: userOnClick
            ? (_id, e) => {
                userOnClick(e);
            }
            : undefined,
        items: hasChildren ? children : undefined
    };
};
const TopNavMeasureItem = ({ link }) => {
    const hasChildren = !!link.links && link.links.length > 0;
    return (_jsxs(StyledTopNavItem, { as: 'span', tabIndex: -1, children: [link.icon && _jsx(Icon, { name: link.icon }), _jsx("span", { children: link.name }), hasChildren && _jsx(Icon, { name: 'caret-down' })] }));
};
const TopNavLink = ({ link }) => {
    const hasChildren = !!link.links && link.links.length > 0;
    const active = hasActiveDescendant(link);
    const triggerRef = useRef(null);
    const popoverRef = useRef(null);
    const [popoverOpen, setPopoverOpen] = useState(false);
    const [filterValue, setFilterValue] = useState('');
    const close = useCallback(() => setPopoverOpen(false), []);
    useFocusWithin([triggerRef, popoverRef], useCallback((isFocused) => {
        if (!isFocused)
            setPopoverOpen(false);
    }, []));
    useEscape(useCallback((e) => {
        if (popoverOpen) {
            setPopoverOpen(false);
            e.stopPropagation();
            triggerRef.current?.focus();
        }
    }, [popoverOpen])
    // No target: attach to document so Escape works when focus is inside the
    // Popover portal (events don't bubble to the trigger element across portals).
    );
    if (hasChildren && link.links) {
        const allItems = link.links.map(linkToFlyoutItem);
        const useFilter = allItems.length >= 5;
        const filterRegex = createStringMatcher(filterValue, 'contains');
        const items = useFilter
            ? allItems.filter(it => filterRegex.test(String(it.primary ?? '')))
            : allItems;
        const handleTriggerClick = () => {
            if (!popoverOpen)
                setFilterValue('');
            setPopoverOpen(v => !v);
        };
        return (_jsxs(_Fragment, { children: [_jsxs(StyledTopNavItem, { ref: triggerRef, "$active": active, "aria-haspopup": 'menu', "aria-expanded": popoverOpen, onClick: handleTriggerClick, children: [link.icon && _jsx(Icon, { name: link.icon }), _jsx("span", { children: link.name }), _jsx(Icon, { name: 'caret-down' })] }), popoverOpen && (_jsx(Popover, { ref: popoverRef, target: triggerRef.current, placement: 'bottom-start', children: _jsx(Menu, { mode: 'action', variant: 'flyout', "aria-label": link.name, items: items, onItemClick: close, focusControlEl: triggerRef.current ?? undefined, ...(useFilter
                            ? {
                                filterInputProps: {
                                    value: filterValue,
                                    onChange: (e) => setFilterValue(e.target.value)
                                }
                            }
                            : {}) }) }))] }));
    }
    const handleClick = e => {
        link.onClick?.(e);
    };
    return (_jsxs(StyledTopNavItem, { href: link.href, onClick: handleClick, "$active": active, "aria-current": link.active ? 'page' : undefined, children: [link.icon && _jsx(Icon, { name: link.icon }), _jsx("span", { children: link.name })] }));
};
const TopNavUtilItem = ({ item, onUtilItemClick }) => {
    const hasMenu = !!item.actions && item.actions.length > 0;
    const triggerRef = useRef(null);
    const popoverRef = useRef(null);
    const [popoverOpen, setPopoverOpen] = useState(false);
    const close = useCallback(() => setPopoverOpen(false), []);
    useFocusWithin([triggerRef, popoverRef], useCallback((isFocused) => {
        if (!isFocused)
            setPopoverOpen(false);
    }, []));
    useEscape(useCallback((e) => {
        if (popoverOpen) {
            setPopoverOpen(false);
            e.stopPropagation();
            triggerRef.current?.focus();
        }
    }, [popoverOpen]));
    if (hasMenu && item.actions) {
        return (_jsxs(_Fragment, { children: [_jsxs(StyledTopNavUtilButton, { ref: triggerRef, "aria-label": item.count ? `${item.name}, ${String(item.count)}` : item.name, "aria-haspopup": 'menu', "aria-expanded": popoverOpen, onClick: () => setPopoverOpen(v => !v), children: [item.visual, !!item.count && (_jsx(StyledTopNavCountBadge, { "aria-hidden": 'true', children: item.count }))] }), popoverOpen && (_jsx(Popover, { ref: popoverRef, target: triggerRef.current, placement: 'bottom-end', children: _jsx(Menu, { mode: 'action', variant: 'flyout', "aria-label": item.name, items: item.actions.map((act) => ({
                            id: act.id ?? act.primary,
                            primary: act.primary,
                            visual: act.visual,
                            href: act.href,
                            onClick: act.onClick
                                ? (_id, e) => {
                                    act.onClick?.(e);
                                    close();
                                }
                                : undefined
                        })), onItemClick: close, focusControlEl: triggerRef.current ?? undefined }) }))] }));
    }
    return (_jsxs(StyledTopNavUtilButton, { "aria-label": item.count ? `${item.name}, ${String(item.count)}` : item.name, onClick: (e) => {
            if (item.drawerView) {
                onUtilItemClick?.(item);
            }
            item.onClick?.(e);
        }, children: [item.visual, !!item.count && (_jsx(StyledTopNavCountBadge, { "aria-hidden": 'true', children: item.count }))] }));
};
const isUtilItemProps = (u) => !isValidElement(u);
const AppTopNav = ({ caseTypes, links, cases, agent, utils, onUtilItemClick }) => {
    const t = useI18n();
    const theme = useTheme();
    const { openDrawer, drawerOpen, openItemName, refreshDrawer } = useContext(AppShellDrawerContext);
    useEffect(() => {
        if (!drawerOpen || !openItemName || !utils)
            return;
        const freshItem = utils.filter(isUtilItemProps).find(u => u.name === openItemName);
        if (freshItem)
            refreshDrawer(freshItem);
    }, [utils, drawerOpen, openItemName, refreshDrawer]);
    const handleUtilItemClick = (item) => {
        if (onUtilItemClick) {
            onUtilItemClick(item);
            return;
        }
        if (item.drawerView) {
            openDrawer(item);
        }
    };
    const navTheme = useMemo(() => {
        const { foreground, interactive, urgent, backgroundColor } = navContrastColors(theme);
        const navBg = theme.components['app-shell'].nav.background;
        return {
            base: {
                palette: {
                    'primary-background': isSolidColor(navBg) ? backgroundColor : 'transparent',
                    'foreground-color': foreground,
                    interactive,
                    urgent
                }
            }
        };
    }, [theme]);
    const linkList = links ?? [];
    const moreButtonRef = useRef(null);
    const { containerRef, measureRef, result } = useTopNavOverflow(linkList, { moreButtonRef });
    const visibleLinks = linkList.slice(0, result.visibleCount);
    const overflowLinks = linkList.slice(result.visibleCount);
    return (_jsx(ThemeOverride, { theme: navTheme, children: _jsxs(StyledTopNav, { "aria-label": t('app_shell_main_navigation_label'), "data-app-region": true, children: [caseTypes && caseTypes.length > 0 && (_jsx(StyledTopNavCreateArea, { container: { alignItems: 'center' }, item: { shrink: 0 }, children: _jsx(CaseTypes, { caseTypes: caseTypes }) })), _jsxs(StyledTopNavList, { ref: containerRef, container: { alignItems: 'center', gap: 1 }, item: { grow: 1 }, children: [_jsx(StyledTopNavMeasureRow, { ref: measureRef, container: { alignItems: 'center', gap: 1 }, "aria-hidden": 'true', children: linkList.map(link => (_jsx(TopNavMeasureItem, { link: link }, link.id))) }), visibleLinks.map(link => (_jsx(TopNavLink, { link: link }, link.id))), _jsxs(StyledTopNavItemHidden, { ref: moreButtonRef, type: 'button', "aria-hidden": 'true', tabIndex: -1, children: [_jsx(Icon, { name: 'bars' }), _jsx("span", { children: t('app_shell_more') })] }), overflowLinks.length > 0 && (_jsx(TopNavMoreMenu, { items: overflowLinks, label: t('app_shell_more'), active: overflowLinks.some(hasActiveDescendant) }))] }), cases && cases.length > 0 && (_jsx(StyledTopNavSection, { container: { alignItems: 'center', gap: 1 }, item: {}, role: 'group', "aria-label": t('active_cases'), children: cases.map(c => (_jsxs(StyledTopNavItem, { onClick: c.onClick, "$active": !!c.active, "aria-current": c.active ? 'page' : undefined, children: [c.visual ?? _jsx(Icon, { name: 'case-solid' }), _jsx("span", { children: c.primary })] }, c.id))) })), _jsxs(StyledTopNavUtilBar, { container: { alignItems: 'center', gap: 1 }, item: { shrink: 0 }, children: [agent && (_jsx(StyledTopNavUtilButton, { "aria-label": agent.name, "aria-current": agent.active ? 'page' : undefined, onClick: (e) => {
                                agent.onClick?.(e);
                            }, children: agent.icon })), utils?.map((util, idx) => {
                            if (isValidElement(util)) {
                                const utilKey = util.key ?? `util-el-${String(idx)}`;
                                return _jsx("span", { children: util }, utilKey);
                            }
                            return (_jsx(TopNavUtilItem, { item: util, onUtilItemClick: handleUtilItemClick }, util.name));
                        })] })] }) }));
};
export default AppTopNav;
//# sourceMappingURL=AppTopNav.js.map