import React, { forwardRef, useState, useReducer, useRef } from "react";
import { safeUseId } from "../../utils";
import { useDidMountEffect, useOutsideClick } from "../../hooks";
import { FloatingPopover } from "./FloatingPopover";
import { focusedReducer } from "./reducers/focusedReducer";
import { SuggestionItem, StyledTextField, VirtualList } from "./ui";
import { Ul, InfiniteLoaderWrapper, base, StyledLeftHelper, ListWrapper } from "./Autocomplete.styles";
import { useKeyNavigation } from "./hooks/useKeyboardNavigation";
/**
 * Компонент Autocomplete. Поле ввода с подсказками в выпадающем списке.
 */ export const autocompleteRoot = (Root)=>/*#__PURE__*/ forwardRef(({ value: outerValue, defaultValue, onChange, suggestions, view, size, labelPlacement, keepPlaceholder, disabled, readOnly, label, leftHelper, contentLeft, contentRight, textBefore, textAfter, onScroll, onBlur, onFocus, listMaxHeight = '25rem', listWidth, portal, zIndex, filter, onSuggestionSelect, threshold = 2, renderList, renderListEnd, renderItem, onSearch, hintText, hintView = 'default', hintSize = 'm', beforeList, afterList, virtual = false, flip = false, rootClassName, rootStyle, // @ts-ignore
    _offset, ...rest }, ref)=>{
        const [focused, dispatchFocused] = useReducer(focusedReducer, null);
        const [innerValue, setInnerValue] = useState(defaultValue || '');
        const [isOpen, setIsOpen] = useState(false);
        const listId = safeUseId();
        const value = outerValue ?? innerValue;
        const helperTextId = safeUseId();
        const floatingPopoverRef = useRef(null);
        const floatingListRef = useRef(null);
        const listWrapperRef = useRef(null);
        const isListMouseDownRef = useRef(false);
        /* Логика работы при клике за пределами выпадающего списка */ useOutsideClick(()=>{
            setIsOpen(false);
        }, [
            floatingPopoverRef,
            listWrapperRef
        ]);
        const handleFocus = (event)=>{
            if (onFocus) {
                onFocus(event);
            }
            if (!readOnly && value.toString().length >= threshold) {
                setIsOpen(true);
            }
        };
        const handleBlur = (event)=>{
            if (onBlur) {
                onBlur(event);
            }
            if (isListMouseDownRef.current) {
                return;
            }
            setIsOpen(false);
        };
        const handleListMouseDown = ()=>{
            isListMouseDownRef.current = true;
            window.setTimeout(()=>{
                isListMouseDownRef.current = false;
            }, 0);
        };
        const handleItemClick = (e)=>{
            setInnerValue(e.label);
            if (onSuggestionSelect) {
                onSuggestionSelect(e);
            }
            setIsOpen(false);
        };
        const handleChange = (e)=>{
            const currentValue = e.target.value;
            setInnerValue(currentValue);
            if (onChange) {
                onChange(e);
            }
            if (currentValue.toString().length >= threshold) {
                setIsOpen(true);
            } else {
                setIsOpen(false);
            }
        };
        const defaultFilterCallback = ({ label })=>{
            return label.toLowerCase().includes(value.toString().toLowerCase());
        };
        const helperTextStopPropagation = (event)=>{
            event.stopPropagation();
        };
        const finalResults = suggestions?.filter(filter || defaultFilterCallback) || [];
        const { onKeyDown } = useKeyNavigation({
            isOpen,
            setIsOpen,
            focused,
            dispatchFocused,
            finalResults,
            handleItemClick
        });
        useDidMountEffect(()=>{
            dispatchFocused({
                type: 'reset'
            });
        }, [
            value
        ]);
        return /*#__PURE__*/ React.createElement(Root, {
            view: view,
            size: size,
            labelPlacement: labelPlacement,
            disabled: disabled,
            readOnly: readOnly,
            hintView: hintView,
            hintSize: hintSize,
            className: rootClassName,
            style: rootStyle
        }, /*#__PURE__*/ React.createElement(FloatingPopover, {
            ref: floatingPopoverRef,
            opened: isOpen,
            portal: portal,
            zIndex: zIndex,
            listWidth: listWidth,
            offset: _offset,
            flip: flip,
            floatingRef: floatingListRef,
            onFloatingMouseDown: handleListMouseDown,
            target: (referenceRef)=>/*#__PURE__*/ React.createElement(StyledTextField, {
                    ref: ref,
                    inputWrapperRef: referenceRef,
                    value: value,
                    onChange: handleChange,
                    onSearch: focused === null ? onSearch : undefined,
                    size: size,
                    view: view,
                    disabled: disabled,
                    readOnly: readOnly,
                    label: label,
                    contentLeft: contentLeft,
                    contentRight: contentRight,
                    textBefore: textBefore,
                    textAfter: textAfter,
                    onFocus: handleFocus,
                    onBlur: handleBlur,
                    onKeyDown: onKeyDown,
                    role: "combobox",
                    "aria-autocomplete": "list",
                    "aria-controls": listId,
                    "aria-expanded": isOpen,
                    "aria-activedescendant": `${listId}/${focused}`,
                    "aria-describedby": helperTextId,
                    hintText: String(hintText || ''),
                    labelPlacement: labelPlacement,
                    keepPlaceholder: keepPlaceholder,
                    leftHelper: leftHelper && /*#__PURE__*/ React.createElement(StyledLeftHelper, {
                        onClick: helperTextStopPropagation
                    }, leftHelper),
                    ...rest
                })
        }, renderList && renderList(finalResults) || Boolean(finalResults.length) && /*#__PURE__*/ React.createElement(Root, {
            view: view,
            size: size,
            labelPlacement: labelPlacement,
            disabled: disabled,
            readOnly: readOnly
        }, /*#__PURE__*/ React.createElement(ListWrapper, {
            ref: listWrapperRef
        }, /*#__PURE__*/ React.createElement(Ul, {
            id: listId,
            role: "listbox",
            "aria-label": label,
            onScroll: virtual ? undefined : onScroll,
            listMaxHeight: listMaxHeight,
            virtual: virtual
        }, virtual ? /*#__PURE__*/ React.createElement(VirtualList, {
            items: finalResults,
            onClick: handleItemClick,
            listId: listId,
            listMaxHeight: listMaxHeight,
            onScroll: onScroll,
            renderItem: renderItem
        }) : /*#__PURE__*/ React.createElement(React.Fragment, null, beforeList, finalResults.map((suggestion, index)=>/*#__PURE__*/ React.createElement(SuggestionItem, {
                key: index,
                item: suggestion,
                onClick: handleItemClick,
                id: `${listId}/${index}`,
                focused: focused === index,
                renderItem: renderItem
            })), afterList), renderListEnd && /*#__PURE__*/ React.createElement(InfiniteLoaderWrapper, null, renderListEnd()))))));
    });
export const autocompleteConfig = {
    name: 'Autocomplete',
    tag: 'div',
    layout: autocompleteRoot,
    base,
    defaults: {
        view: 'default',
        size: 'l',
        labelPlacement: 'outer'
    },
    variations: {
        view: {
            css: ''
        }
    }
};
