import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { forwardRef, useRef, useCallback, useMemo, useState, useEffect } from 'react';
import styled from 'styled-components';
import { defaultThemeProp } from '../../../theme';
import Selectable from '../../Badges/Selection';
import { StyledFormControl } from '../../FormControl';
import Flex from '../../Flex';
import { useConsolidatedRef, useActiveDescendant, useDirection, useI18n, useUID } from '../../../hooks';
import { cap } from '../../../utils';
import VisuallyHiddenText from '../../VisuallyHiddenText';
import { StyledSelectInput } from '../ComboBox.styles';
export const StyledMultiSelectInput = styled(StyledSelectInput) `
  cursor: text;

  ul {
    list-style: none;
    display: contents;
  }

  input {
    width: 8ch;
    height: 1.125rem;
  }
`;
StyledMultiSelectInput.defaultProps = defaultThemeProp;
const MultiSelectInput = forwardRef(function MultiSelectInput(props, ref) {
    const { selected = [], value, onRemove, onChange, onKeyDown, onResolveSuggestion, actions, readOnly, disabled, status, placeholder, autoFocus, pauseDescendantEvaluation, onSelectedFocus, onSelectedBlur, 'aria-controls': ariaControls, ...restProps } = props;
    const t = useI18n();
    const id = useUID();
    const inputRef = useConsolidatedRef(ref);
    const listRef = useRef(null);
    const [focusDescendant, setFocusDescendant] = useState(null);
    const [activeItemId, setActiveItemId] = useState(null);
    const { start, end } = useDirection();
    const uadConfig = useMemo(() => ({
        focusEl: inputRef.current,
        scope: listRef.current,
        selector: 'li[role="option"]',
        orientation: 'horizontal',
        focusReturnEl: focusDescendant,
        clearFocusReturn: () => {
            setFocusDescendant(null);
        },
        pauseDescendantEvaluation,
        preventInitialScroll: true,
        onClick: (el) => {
            el.click();
        }
    }), [pauseDescendantEvaluation, selected, focusDescendant]);
    const { activeDescendant } = useActiveDescendant(uadConfig, [selected]);
    const handleSelectedRemoval = useCallback((selectionId, idx) => {
        if (!pauseDescendantEvaluation) {
            if (idx === selected.length - 1) {
                // If removing last selected item
                if (selected.length > 1) {
                    // If other selected items, focus previous
                    setFocusDescendant(listRef.current?.querySelectorAll(uadConfig.selector)[idx - 1] ||
                        null);
                }
                else {
                    // Blur selected if final only item removed
                    onSelectedBlur?.();
                }
            }
            else if (selected.length > 1) {
                // If not last item removed and other selected items, focus next
                setFocusDescendant(listRef.current?.querySelectorAll(uadConfig.selector)[idx + 1] ||
                    null);
            }
        }
        onRemove?.(selectionId, idx);
        inputRef.current?.focus();
    }, [selected, onRemove, onSelectedBlur, uadConfig]);
    useEffect(() => {
        // Maintain active item & prev. val only as it changes.
        if (activeDescendant?.id && activeDescendant.id !== activeItemId) {
            setActiveItemId(activeDescendant.id);
        }
    }, [activeDescendant]);
    const onInputKeyDown = useCallback((e) => {
        if (selected.length && inputRef.current?.selectionStart === 0) {
            const lastIndex = selected.length - 1;
            if (pauseDescendantEvaluation && e.key === `Arrow${cap(start)}`) {
                setFocusDescendant(listRef.current?.querySelectorAll(uadConfig.selector)[lastIndex] ||
                    null);
                onSelectedFocus?.();
            }
            const lastSelectableId = listRef.current?.querySelectorAll(uadConfig.selector)[lastIndex]
                ?.id;
            const onLastItem = activeItemId === lastSelectableId;
            if (!pauseDescendantEvaluation &&
                ((onLastItem && e.key === `Arrow${cap(end)}`) || e.key === 'ArrowDown')) {
                onSelectedBlur?.();
            }
            if (['Backspace', 'Delete'].includes(e.key) && !(readOnly || disabled)) {
                handleSelectedRemoval(selected[lastIndex].id, lastIndex);
            }
        }
        onKeyDown?.(e);
    }, [
        pauseDescendantEvaluation,
        activeItemId,
        onKeyDown,
        handleSelectedRemoval,
        selected,
        readOnly,
        disabled
    ]);
    const ariaDescribedBy = useMemo(() => {
        return onChange
            ? `${id}-inputDescription  ${id}-searchDescription`
            : `${id}-inputDescription`;
    }, [id]);
    const ariaControlsValue = useMemo(() => {
        if (!pauseDescendantEvaluation) {
            return selected.length > 0 ? id : undefined;
        }
        return ariaControls;
    }, [pauseDescendantEvaluation, selected.length]);
    return (_jsxs(Flex, { as: StyledMultiSelectInput, forwardedAs: StyledFormControl, hasSuggestion: status === 'pending' && !!onResolveSuggestion, container: { alignItems: 'center', justify: 'between' }, readOnly: readOnly, disabled: disabled, status: status, children: [_jsxs(Flex, { container: { alignContent: 'center', wrap: 'wrap', rowGap: 0.5, colGap: 0.25, pad: 0.25 }, item: { grow: 1 }, onClick: (e) => {
                    // Ignore clicks on selection items
                    if (e.target instanceof HTMLElement &&
                        !(e.target instanceof HTMLInputElement) &&
                        !e.currentTarget.contains(e.target.closest('li'))) {
                        e.stopPropagation();
                        inputRef.current?.focus();
                        inputRef.current?.click();
                    }
                }, children: [selected.length > 0 && (_jsx("ul", { ref: listRef, id: id, role: 'listbox', "aria-label": t('selected_items'), children: selected.map((element, idx) => {
                            return (_jsx(Selectable, { as: 'li', role: 'option', id: element.id.toString(), status: status, onClick: e => {
                                    const mouseClick = e.detail > 0;
                                    if (!readOnly && !disabled && !mouseClick) {
                                        handleSelectedRemoval(element.id, idx);
                                    }
                                }, onRemove: () => {
                                    if (!readOnly && !disabled) {
                                        handleSelectedRemoval(element.id, idx);
                                    }
                                }, onKeyDown: (e) => {
                                    // prevent browser's Back on FF
                                    if (e.key === 'Backspace')
                                        e.preventDefault();
                                }, tabIndex: '-1', "aria-label": `${t('remove')} ${element.text}`, "aria-describedby": ariaDescribedBy, children: element.text }, element.id));
                        }) })), _jsx(Flex, { item: { grow: 1 }, as: 'input', size: 1, ref: inputRef, value: value, 
                        // no-op avoids react uncontrolled warning
                        onChange: onChange || (() => { }), onKeyDown: onInputKeyDown, readOnly: readOnly || !onChange, disabled: disabled, placeholder: selected?.length ? undefined : placeholder, autoComplete: 'off', autoFocus: autoFocus, "aria-controls": ariaControlsValue, ...restProps, required: undefined })] }), actions, _jsx(VisuallyHiddenText, { id: `${id}-inputDescription`, children: `${t('combobox_open_close')} ` }), _jsx(VisuallyHiddenText, { id: `${id}-searchDescription`, children: t('combobox_search_instructions') })] }));
});
export default MultiSelectInput;
//# sourceMappingURL=MultiSelectInput.js.map