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, 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 * as wrapIcon from '../Icon/icons/wrap.icon';
import * as unwrapIcon from '../Icon/icons/unwrap.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 Text from '../Text';
import PresetMenuPopover from './PresetMenuPopover';
import { StyledViewSelector, StyledSearchForm, StyledListToolbar, StyledHeading, StyledCountMeta, StyledListToolbarContent, StyledListToolbarDialog, StyledErrorIcon, StyledInfo, StyledSearchContainer, StyledExpandSearchButton } from './ListToolbar.styles';
import helpers from './helpers';
import { getListToolbarTestIds } from './ListToolbar.test-ids';
registerIcon(filterIcon, arrowUpDownIcon, rowIcon, plusIcon, moreIcon, wrapIcon, unwrapIcon);
const CountMeta = ({ count, ...restProps }) => {
    const { locale } = useConfiguration();
    const t = useI18n();
    const totalFormattedValue = formatNumber(count.total ?? 0, {
        locale,
        options: {
            useGrouping: true
        }
    });
    return (_jsx(StyledCountMeta, { variant: 'default', ...restProps, children: count.selected
            ? t('selected_count', [formatNumber(count.selected, { locale, options: { useGrouping: true } })], { count: count.selected })
            : t('results_count', [count.totalHasMore ? `${totalFormattedValue}+` : totalFormattedValue], {
                count: count.total
            }) }));
};
const ListToolbar = forwardRef(function ListToolbar({ testId, name, showName = true, headingTag = 'h2', viewSelector, formControlProps, createNew, search, count, wrap, 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 [headingEl, setHeadingEl] = useElement();
    const [labelEl, setLabelEl] = useElement();
    const [isSearchOpen, setIsSearchOpen] = useState(!!search?.value);
    const isSmallOrAbove = useBreakpoint('sm', { breakpointRef: toolbarContentRef });
    useEffect(() => {
        if (search?.value) {
            setIsSearchOpen(true);
        }
    }, [search?.value]);
    useEffect(() => {
        if (!isSearchOpen || search?.value)
            return;
        const openedSearch = searchInputRef.current?.parentElement;
        if (!openedSearch)
            return;
        const handleFocusOut = (e) => {
            if (!search?.value && !openedSearch.contains(e.relatedTarget)) {
                setIsSearchOpen(false);
            }
        };
        openedSearch.addEventListener('focusout', handleFocusOut);
        return () => {
            openedSearch.removeEventListener('focusout', handleFocusOut);
        };
    }, [isSearchOpen, 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, icon: true, label: text, onClick: createNew.onClick, children: _jsx(Icon, { name: 'plus' }) }));
    }, [t, createNew, isSmallOrAbove]);
    const wrapButton = useMemo(() => {
        if (!wrap)
            return null;
        const text = wrap.enabled ? t('disable_word_wrap') : t('enable_word_wrap');
        return (_jsx(Button, { "data-testid": testIds.wrapButton, variant: 'simple', icon: true, label: text, "aria-label": text, onClick: wrap.onClick, children: _jsx(Icon, { name: wrap.enabled ? 'unwrap' : 'wrap' }) }));
    }, [wrap, isSmallOrAbove, t]);
    const searchInput = useMemo(() => (_jsx(SearchInput, { "data-testid": testIds.searchInput, ...search, onSearchSubmit: (value) => {
            search?.onSearchSubmit?.(value);
        }, onClick: (e) => {
            e.preventDefault();
        }, ref: searchInputRef })), [search]);
    const searchLabel = t('search');
    const expandableSearch = useMemo(() => {
        return isSearchOpen ? (searchInput) : (_jsx(StyledExpandSearchButton, { "data-testid": testIds.searchButton, variant: 'simple', icon: true, label: searchLabel, "aria-label": t('expand_search'), 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]);
    const smallScreenActions = useMemo(() => {
        let basicActions = [];
        if (createNew && createNew.onClick) {
            const text = createNew.label ?? t('create_new');
            const createNewAction = {
                text,
                id: text,
                icon: 'plus',
                'aria-label': text,
                onClick: (_, e) => createNew.onClick(e),
                'data-testid': testIds.createNew
            };
            basicActions.push(createNewAction);
        }
        if (wrap) {
            const text = wrap.enabled ? t('disable_word_wrap') : t('enable_word_wrap');
            const wrapAction = {
                text,
                id: text,
                icon: wrap.enabled ? 'unwrap' : 'wrap',
                'aria-label': text,
                onClick: (_, e) => wrap.onClick(e),
                'data-testid': testIds.wrapButton
            };
            basicActions.push(wrapAction);
        }
        if (basicModeActions) {
            basicActions = basicActions.concat(basicModeActions);
        }
        return basicActions.length ? basicActions : undefined;
    }, [createNew?.label, createNew?.onClick, wrap?.enabled, wrap?.onClick, basicModeActions]);
    let labelText = name;
    const viewItems = helpers.getViews(viewSelector?.views ?? []);
    const shouldRenderViewSelector = viewSelector &&
        (viewSelector.views.length > 1 ||
            (!!viewSelector.views.length && !!viewSelector.onCreateView) ||
            (!!viewSelector.views.length && !!viewSelector.filterInputProps));
    const selectedViewName = shouldRenderViewSelector && !!viewItems.length
        ? helpers.getSelectedView(viewSelector.views)?.text ?? viewItems[0].text
        : '';
    if (selectedViewName) {
        labelText = `${name}: ${selectedViewName}`;
    }
    return (_jsxs(Flex, { "data-testid": testIds.root, container: true, ...restProps, as: StyledListToolbar, ref: ref, isSmallOrAbove: isSmallOrAbove, children: [_jsxs(StyledListToolbarContent, { container: { direction: 'column' }, ref: toolbarContentRef, item: { grow: 1 }, children: [_jsxs(Flex, { container: {
                            alignItems: 'center',
                            justify: 'between',
                            direction: 'row'
                        }, children: [_jsxs(Flex, { container: {
                                    alignItems: isSmallOrAbove ? 'center' : undefined,
                                    justify: 'between',
                                    direction: isSmallOrAbove ? undefined : 'column'
                                }, item: { grow: 1 }, children: [_jsxs(Flex, { container: {
                                            alignItems: 'center',
                                            gap: 1
                                        }, item: { grow: 1 }, children: [_jsxs(StyledHeading, { "data-testid": testIds.heading, required: formControlProps?.required, showName: showName, "aria-describedby": formControlProps?.info ? `${uid}-info` : undefined, children: [_jsxs(Text, { variant: headingTag, ref: setHeadingEl, required: formControlProps?.required, children: [name, shouldRenderViewSelector && _jsx(_Fragment, { children: ":\u00A0" })] }), _jsx(Tooltip, { target: headingEl, describeTarget: false, hideDelay: 'none', smart: true, children: name }), shouldRenderViewSelector && (_jsxs(_Fragment, { children: [_jsx(MenuButton, { ref: setLabelEl, "data-testid": testIds.viewSelector, variant: 'link', text: selectedViewName, 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: groupedView.text,
                                                                                        visual: groupedView.visual ? (_jsx(Avatar, { ...groupedView.visual })) : undefined
                                                                                    };
                                                                                })
                                                                            };
                                                                        }
                                                                        const { visual, ...restView } = view;
                                                                        return {
                                                                            ...restView,
                                                                            primary: view.text,
                                                                            visual: visual ? _jsx(Avatar, { ...visual }) : undefined
                                                                        };
                                                                    }),
                                                                    onItemClick: viewSelector.onViewSelect,
                                                                    filterInputProps: viewSelector.filterInputProps,
                                                                    ...(viewSelector.onCreateView &&
                                                                        labelEl && {
                                                                        onCreateNew: {
                                                                            text: t('list_toolbar_add_view'),
                                                                            handler: () => {
                                                                                viewSelector.onCreateView?.(labelEl);
                                                                            }
                                                                        }
                                                                    })
                                                                } }), labelEl && (_jsx(Tooltip, { target: labelEl, describeTarget: false, hideDelay: 'none', smart: true, children: selectedViewName }))] }))] }), 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 && wrapButton, isSmallOrAbove && _jsx(FullscreenButton, {}), isSmallOrAbove && basicModeActions && (_jsx(Actions, { contextualLabel: labelText, items: basicModeActions.map(({ icon, ...restActionProps }) => ({
                                                    ...restActionProps,
                                                    visual: icon && _jsx(Icon, { name: icon })
                                                })), menuAt: 1, ref: consolidatedActionsButtonRef })), isSmallOrAbove && createNewButton, !isSmallOrAbove && count && (_jsx(CountMeta, { "data-testid": testIds.count, count: count }))] })] }), !isSmallOrAbove && (_jsxs(_Fragment, { children: [_jsx(FullscreenButton, {}), smallScreenActions && (_jsx(Actions, { contextualLabel: labelText, items: smallScreenActions.map(({ icon, ...restActionProps }) => ({
                                            ...restActionProps,
                                            visual: icon && _jsx(Icon, { name: icon })
                                        })), menuAt: 1, ref: consolidatedActionsButtonRef }))] }))] }), !isSmallOrAbove && (search || (count && !!count.selected)) && (_jsx(StyledSearchContainer, { container: { alignItems: 'start', justify: 'between' }, children: _jsxs(Flex, { as: StyledSearchForm, container: { alignItems: 'stretch', wrap: 'wrap', gap: 1, direction: 'column' }, item: { grow: 1 }, children: [search && searchInput, count && !!count.selected && additionalActions] }) })), formControlProps?.info && (_jsxs(StyledInfo, { role: formControlProps.status === 'error' || formControlProps.status === 'warning'
                            ? 'alert'
                            : undefined, id: `${uid}-info`, "data-testid": testIds.info, status: formControlProps.status, children: [formControlProps.status === 'error' && (_jsxs(_Fragment, { children: [_jsx(StyledErrorIcon, { name: 'warn-solid' }), _jsx(VisuallyHiddenText, { children: ` ${t('error')} ` })] })), 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