import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import VisuallyHiddenText from '../VisuallyHiddenText';
import Actions from '../Actions';
import Button from '../Button';
import { useBreakpoint, useConfiguration, useConsolidatedRef, useElement, useEscape, useI18n, useTestIds, useUID } from '../../hooks';
import Flex from '../Flex';
import SearchInput from '../SearchInput';
import Icon, { registerIcon } from '../Icon';
import * as filterIcon from '../Icon/icons/filter.icon';
import * as arrowUpDownIcon from '../Icon/icons/arrow-up-down.icon';
import * as rowIcon from '../Icon/icons/row.icon';
import * as plusIcon from '../Icon/icons/plus.icon';
import * as moreIcon from '../Icon/icons/more.icon';
import { hasProp, withTestIds } from '../../utils';
import { formatNumber } from '../Number';
import MenuButton from '../MenuButton';
import Avatar from '../Avatar';
import AdditionalInfo from '../AdditionalInfo';
import FullscreenButton from '../Fullscreen/FullscreenButton';
import Tooltip from '../Tooltip';
import PresetMenuPopover from './PresetMenuPopover';
import { StyledViewSelector, StyledSearchForm, StyledListToolbar, StyledHeadingText, StyledCountMeta, StyledListToolbarContent, StyledListToolbarDialog, StyledErrorIcon, StyledInfo, StyledSearchContainer } from './ListToolbar.styles';
import helpers from './helpers';
import { getListToolbarTestIds } from './ListToolbar.test-ids';
registerIcon(filterIcon, arrowUpDownIcon, rowIcon, plusIcon, moreIcon);
const CountMeta = ({ count, ...restProps }) => {
    const { locale } = useConfiguration();
    const t = useI18n();
    const totalFormattedValue = formatNumber(count.total ?? 0, {
        locale,
        options: {
            useGrouping: true
        }
    });
    return (_jsx(StyledCountMeta, { variant: 'secondary', ...restProps, children: count.selected
            ? t('selected_count', [formatNumber(count.selected, { locale, options: { useGrouping: true } })], { count: count.selected })
            : count.total !== undefined &&
                t('results_count', [count.totalHasMore ? `${totalFormattedValue}+` : totalFormattedValue], {
                    count: count.total
                }) }));
};
const generateViewName = (view, texts, options) => {
    return `${view.text} ${view.id === options.defaultId ? `(${texts.default})` : ''} ${view.id === options.appDefaultId ? `(${texts.appDefault})` : ''}`;
};
const ListToolbar = forwardRef(function ListToolbar({ testId, name, headingTag = 'h3', viewSelector, formControlProps, createNew, search, count, additionalActions, filter, sort, group, actions, actionsButtonRef, ...restProps }, ref) {
    const uid = useUID();
    const t = useI18n();
    const testIds = useTestIds(testId, getListToolbarTestIds);
    const consolidatedActionsButtonRef = useConsolidatedRef(actionsButtonRef);
    const toolbarContentRef = useRef(null);
    const searchInputRef = useRef(null);
    const searchButtonRef = useRef(null);
    const [labelEl, setLabelEl] = useElement();
    const [isSearchOpen, setIsSearchOpen] = useState(!!search?.value);
    const isSmallOrAbove = useBreakpoint('sm', { breakpointRef: toolbarContentRef });
    const onSearchEscape = () => {
        if (!search?.value) {
            setIsSearchOpen(false);
        }
        setTimeout(() => searchButtonRef.current?.focus());
    };
    useEffect(() => {
        if (search?.value) {
            setIsSearchOpen(true);
        }
    }, [search?.value]);
    const [currentQueryOptionId, setCurrentQueryOptionId] = useState(null);
    const queryOptionPopoverTarget = useRef();
    const [actionsQueryOptionPreset, setActionsQueryOptionPreset] = useState();
    const [optionPresetMenuOpen, setOptionPresetMenuOpen] = useState(false);
    const createNewButton = useMemo(() => {
        if (!createNew?.onClick)
            return null;
        const text = createNew.label ?? t('create_new');
        return (_jsx(Button, { "data-testid": testIds.createNew, variant: 'simple', icon: true, label: text, "aria-label": text, onClick: createNew.onClick, children: _jsx(Icon, { name: 'plus' }) }));
    }, [t, createNew, isSmallOrAbove]);
    useEscape(onSearchEscape, searchInputRef);
    const searchInput = useMemo(() => (_jsx(SearchInput, { "data-testid": testIds.searchInput, ...search, onSearchSubmit: (value) => {
            search?.onSearchSubmit?.(value);
            onSearchEscape();
        }, onClick: (e) => {
            e.preventDefault();
        }, onBlur: () => {
            if (!search?.value) {
                setIsSearchOpen(false);
            }
        }, ref: searchInputRef })), [search, onSearchEscape]);
    const searchLabel = t('search');
    const expandableSearch = useMemo(() => {
        return isSearchOpen ? (searchInput) : (_jsx(Button, { "data-testid": testIds.searchButton, variant: 'simple', icon: true, label: searchLabel, onClick: () => {
                setIsSearchOpen(true);
                setTimeout(() => searchInputRef.current?.focus());
            }, onKeyDown: (e) => {
                if (e.target !== searchInputRef.current && (e.key === 'Enter' || e.key === ' ')) {
                    setIsSearchOpen(true);
                    setTimeout(() => {
                        searchInputRef.current?.focus();
                        searchInputRef.current?.select();
                    });
                }
            }, ref: searchButtonRef, children: _jsx(Icon, { name: 'search' }) }));
    }, [searchLabel, setIsSearchOpen, isSearchOpen, searchInput]);
    let queryOptionPopover = null;
    if (currentQueryOptionId) {
        const queryOptionProps = { filter, sort, group }[currentQueryOptionId];
        if (queryOptionProps &&
            hasProp(queryOptionProps, 'renderer') &&
            queryOptionPopoverTarget.current) {
            queryOptionPopover = (_jsx(StyledListToolbarDialog, { target: queryOptionPopoverTarget.current, heading: t(currentQueryOptionId), placement: 'bottom-end', onCancel: () => {
                    if (queryOptionProps.onCancel() === false)
                        return;
                    setCurrentQueryOptionId(null);
                }, onSubmit: () => {
                    if (queryOptionProps.onSubmit() === false)
                        return;
                    setCurrentQueryOptionId(null);
                }, children: _jsx(queryOptionProps.renderer, { ...(queryOptionProps.rendererProps || {}) }) }));
        }
    }
    const getQueryOptionAction = useCallback((id, icon, queryOptionProps) => {
        return {
            text: t(id),
            id,
            icon,
            count: queryOptionProps.count,
            onClick: () => {
                if (hasProp(queryOptionProps, 'renderer')) {
                    setCurrentQueryOptionId(id);
                    queryOptionPopoverTarget.current = consolidatedActionsButtonRef.current ?? undefined;
                }
                if (hasProp(queryOptionProps, 'items')) {
                    setActionsQueryOptionPreset({
                        heading: t(id),
                        menu: {
                            mode: queryOptionProps.mode,
                            items: queryOptionProps.items.map(item => ({ ...item, primary: item.text })),
                            onItemClick: queryOptionProps.onItemClick
                        }
                    });
                    setOptionPresetMenuOpen(true);
                }
            }
        };
    }, []);
    const basicModeActions = useMemo(() => {
        let basicActions = [];
        if (filter) {
            const filterAction = getQueryOptionAction('filter', 'filter', filter);
            basicActions.push(filterAction);
        }
        if (sort) {
            const sortAction = getQueryOptionAction('sort', 'arrow-up-down', sort);
            basicActions.push(sortAction);
        }
        if (group) {
            const groupAction = getQueryOptionAction('group', 'row', group);
            basicActions.push(groupAction);
        }
        if (actions) {
            basicActions = basicActions.concat(actions);
        }
        return basicActions.length ? basicActions : undefined;
    }, [actions, filter, sort, group, getQueryOptionAction]);
    let labelText = name;
    if (viewSelector) {
        const viewItems = helpers.getViews(viewSelector.views);
        if (viewItems.length > 1) {
            const selectedViewName = helpers.getSelectedView(viewSelector.views)?.text ?? viewItems[0].text;
            labelText = `${name}: ${selectedViewName}`;
        }
    }
    return (_jsxs(Flex, { "data-testid": testIds.root, container: true, ...restProps, as: StyledListToolbar, ref: ref, children: [_jsxs(StyledListToolbarContent, { container: { direction: 'column', pad: [0.5, 0.5, 0.5, undefined] }, ref: toolbarContentRef, item: { grow: 1 }, children: [_jsxs(Flex, { container: {
                            alignItems: 'center',
                            justify: 'between',
                            gap: 0.5
                        }, children: [_jsxs(Flex, { container: {
                                    alignItems: 'center',
                                    gap: 1
                                }, item: { grow: 1 }, children: [_jsxs(StyledHeadingText, { "data-testid": testIds.heading, variant: headingTag, required: formControlProps?.required, "aria-describedby": formControlProps?.info ? `${uid}-info` : undefined, children: [formControlProps?.info && formControlProps.status === 'error' && (_jsxs(_Fragment, { children: [_jsx(StyledErrorIcon, { name: 'warn-solid' }), _jsx(VisuallyHiddenText, { children: ` ${t('error')} ` })] })), !viewSelector || viewSelector.views.length <= 1 ? (labelText) : (_jsxs(_Fragment, { children: [_jsx(MenuButton, { ref: setLabelEl, "data-testid": testIds.viewSelector, variant: 'text', text: labelText, as: StyledViewSelector, menu: {
                                                            mode: 'single-select',
                                                            items: viewSelector.views.map(view => {
                                                                if (hasProp(view, 'items')) {
                                                                    return {
                                                                        id: view.text,
                                                                        label: view.text,
                                                                        items: view.items.map(groupedView => {
                                                                            return {
                                                                                ...groupedView,
                                                                                primary: generateViewName(groupedView, { default: t('default'), appDefault: t('app_default') }, {
                                                                                    defaultId: viewSelector.defaultId,
                                                                                    appDefaultId: viewSelector.appDefaultId
                                                                                }),
                                                                                visual: groupedView.visual ? (_jsx(Avatar, { ...groupedView.visual })) : undefined
                                                                            };
                                                                        })
                                                                    };
                                                                }
                                                                return {
                                                                    ...view,
                                                                    primary: generateViewName(view, { default: t('default'), appDefault: t('app_default') }, {
                                                                        defaultId: viewSelector.defaultId,
                                                                        appDefaultId: viewSelector.appDefaultId
                                                                    }),
                                                                    visual: view.visual ? _jsx(Avatar, { ...view.visual }) : undefined
                                                                };
                                                            }),
                                                            onItemClick: viewSelector.onViewSelect
                                                        } }), labelEl && (_jsx(Tooltip, { target: labelEl, describeTarget: false, hideDelay: 'none', smart: true, children: labelText }))] }))] }), formControlProps?.additionalInfo && (_jsx(AdditionalInfo, { heading: formControlProps.additionalInfo.heading, contextualLabel: labelText, children: formControlProps.additionalInfo.content })), isSmallOrAbove && count && _jsx(CountMeta, { "data-testid": testIds.count, count: count })] }), _jsxs(_Fragment, { children: [isSmallOrAbove && additionalActions, search && isSmallOrAbove && expandableSearch, isSmallOrAbove && createNewButton, isSmallOrAbove && _jsx(FullscreenButton, {}), isSmallOrAbove && basicModeActions && (_jsx(Actions, { contextualLabel: name, items: basicModeActions.map(({ icon, ...restActionProps }) => ({
                                            ...restActionProps,
                                            visual: icon && _jsx(Icon, { name: icon })
                                        })), menuAt: 1, ref: consolidatedActionsButtonRef })), !isSmallOrAbove && count && _jsx(CountMeta, { "data-testid": testIds.count, count: count })] })] }), !isSmallOrAbove && (_jsxs(_Fragment, { children: [!!count?.selected && additionalActions, _jsxs(StyledSearchContainer, { container: { alignItems: 'start', justify: 'between', gap: 1 }, children: [_jsx(Flex, { as: StyledSearchForm, container: { alignItems: 'center', wrap: 'wrap', gap: 1 }, item: { grow: 1 }, children: search && searchInput }), createNewButton, _jsx(FullscreenButton, {}), basicModeActions && (_jsx(Actions, { contextualLabel: name, items: basicModeActions.map(({ icon, ...restActionProps }) => ({
                                            ...restActionProps,
                                            visual: icon && _jsx(Icon, { name: icon })
                                        })), menuAt: 1, ref: consolidatedActionsButtonRef }))] })] })), formControlProps?.info && (_jsx(StyledInfo, { role: formControlProps.status === 'error' || formControlProps.status === 'warning'
                            ? 'alert'
                            : undefined, id: `${uid}-info`, "data-testid": testIds.info, status: formControlProps.status, children: formControlProps.info }))] }), queryOptionPopover, _jsx(PresetMenuPopover, { buttonRef: consolidatedActionsButtonRef, heading: actionsQueryOptionPreset?.heading, menu: actionsQueryOptionPreset?.menu, isOpen: optionPresetMenuOpen, onClose: () => setOptionPresetMenuOpen(false) })] }));
});
export default withTestIds(ListToolbar, getListToolbarTestIds);
//# sourceMappingURL=ListToolbar.js.map