import React, { useMemo, useRef, useState } from "react";
import { useClientLayoutEffect } from "../../../utils-external/index.js";
import { DismissableLayer } from "../../../utils/components/dismissablelayer/DismissableLayer.js";
import { Floating } from "../../../utils/components/floating/Floating.js";
import { cl } from "../../../utils/helpers/index.js";
import { useInputContext } from "../Input/Input.context.js";
import { useSelectedOptionsContext } from "../SelectedOptions/selectedOptionsContext.js";
import AddNewOption from "./AddNewOption.js";
import FilteredOptionsItem from "./FilteredOptionsItem.js";
import LoadingMessage from "./LoadingMessage.js";
import MaxSelectedMessage from "./MaxSelectedMessage.js";
import NoSearchHitsMessage from "./NoSearchHitsMessage.js";
import filteredOptionsUtil from "./filtered-options-util.js";
import { useFilteredOptionsContext } from "./filteredOptionsContext.js";
const FilteredOptions = () => {
    const { inputProps: { id }, anchorRef, } = useInputContext();
    const { allowNewValues, isLoading, isListOpen, filteredOptions, setFilteredOptionsRef, isMouseLastUsedInputDevice, isValueNew, toggleIsListOpen, } = useFilteredOptionsContext();
    const [localOpen, setLocalOpen] = useState(isListOpen);
    const floatingRef = useRef(null);
    /**
     * This is a dirty hack to make the positioning-logic in Floating base the "flip" on the static 290px max-height,
     * instead of the dynamic one based on available space. Without this, the list won't flip to top when there's
     * not enough space below the input.
     */
    useClientLayoutEffect(() => {
        queueMicrotask(() => setLocalOpen(isListOpen));
    }, [isListOpen]);
    const { maxSelected, isMultiSelect, selectedOptions } = useSelectedOptionsContext();
    const shouldRenderNonSelectables = (isMultiSelect && maxSelected.limit) || // Render maxSelected message
        isLoading || // Render loading message
        (!isLoading && filteredOptions.length === 0 && !allowNewValues); // Render no hits message
    const singleSelectedOption = useMemo(() => {
        if (isMultiSelect ||
            selectedOptions.length === 0 ||
            selectedOptions.length > 1) {
            return null;
        }
        return selectedOptions[0];
    }, [isMultiSelect, selectedOptions]);
    const shouldRenderFilteredOptionsList = (allowNewValues && isValueNew && !maxSelected.isLimitReached) || // Render add new option
        filteredOptions.length > 0 || // Render filtered options
        !!singleSelectedOption;
    return (React.createElement(DismissableLayer, { asChild: true, safeZone: {
            anchor: anchorRef,
        }, onDismiss: () => localOpen && toggleIsListOpen(false), onEscapeKeyDown: (event) => {
            /* We handle this manually in Input */
            event.preventDefault();
        }, enabled: localOpen },
        React.createElement(Floating.Content, { ref: floatingRef, className: cl("aksel-combobox__list", {
                "aksel-combobox__list--closed": !isListOpen,
                "aksel-combobox__list--with-hover": isMouseLastUsedInputDevice,
            }), id: filteredOptionsUtil.getFilteredOptionsId(id), tabIndex: -1, sideOffset: 8, side: "bottom", fallbackPlacements: ["top"], enabled: isListOpen, style: {
                maxHeight: localOpen
                    ? `min(316px, var(--__axc-floating-available-height))`
                    : `316px`,
            }, autoUpdateWhileMounted: false },
            shouldRenderNonSelectables && (React.createElement("div", { className: "aksel-combobox__list_non-selectables", role: "status" },
                isMultiSelect && maxSelected.limit && React.createElement(MaxSelectedMessage, null),
                isLoading && React.createElement(LoadingMessage, null),
                !isLoading && filteredOptions.length === 0 && !allowNewValues && (React.createElement(NoSearchHitsMessage, null)))),
            shouldRenderFilteredOptionsList && (React.createElement("ul", { ref: setFilteredOptionsRef, role: "listbox", className: "aksel-combobox__list-options" },
                isValueNew && !maxSelected.isLimitReached && allowNewValues && (React.createElement(AddNewOption, null)),
                singleSelectedOption && (React.createElement(FilteredOptionsItem, { key: singleSelectedOption.value, option: singleSelectedOption })),
                filteredOptions.map((option) => {
                    if (singleSelectedOption &&
                        option.value === singleSelectedOption.value) {
                        return null;
                    }
                    return React.createElement(FilteredOptionsItem, { key: option.value, option: option });
                }))))));
};
export default FilteredOptions;
//# sourceMappingURL=FilteredOptions.js.map