import React, { forwardRef, useCallback, useState } from "react";
import { Search } from "../../form/search/index.js";
import { VStack } from "../../primitives/stack/index.js";
import { BodyShort, Detail } from "../../typography/index.js";
import Listbox from "../../utils/components/Listbox/root/ListboxRoot.js";
import { DismissableLayer } from "../../utils/components/dismissablelayer/DismissableLayer.js";
import { Floating } from "../../utils/components/floating/Floating.js";
import { useMergeRefsN } from "../../utils/hooks/index.js";
const AutoSuggest = forwardRef(({ options, onSelect, value, onChange, open, setOpen }, ref) => {
    const [virtuallyFocusedOptionId, setVirtuallyFocusedOptionId] = useState("");
    const [inputRef, setInputRef] = useState(null);
    /* Unsure why N version works, but not regular here */
    const mergedRef = useMergeRefsN([setInputRef, ref]);
    const handleClose = () => {
        setOpen(false);
    };
    const handleChange = (newValue) => {
        onChange(newValue);
        setOpen(true);
    };
    const handleSelectOption = useCallback((option) => {
        const createdNewToken = onSelect(option);
        if (createdNewToken) {
            inputRef === null || inputRef === void 0 ? void 0 : inputRef.focus();
            setOpen(false);
        }
    }, [onSelect, inputRef, setOpen]);
    return (React.createElement(Floating, null,
        React.createElement(Listbox, { setVirtuallyFocusedOptionId: setVirtuallyFocusedOptionId },
            React.createElement(Floating.Anchor, null,
                React.createElement(Listbox.InputSlot, null,
                    React.createElement(Search, { label: "Tabells\u00F8k", variant: "simple", className: "aksel-property-filter__input", placeholder: "Type to filter...", ref: mergedRef, value: value, onChange: handleChange, onClick: () => {
                            setOpen(true);
                        }, onFocus: () => setOpen(true), size: "small", autoComplete: "off" }))),
            open && (React.createElement(AutoSuggestPopup, { options: options, onSelect: handleSelectOption, focusedValue: virtuallyFocusedOptionId, onClose: handleClose, safeZoneAnchor: inputRef, autoSuggestValue: value })))));
});
const AutoSuggestPopup = forwardRef(({ options, onSelect, focusedValue, onClose, safeZoneAnchor, autoSuggestValue, }, ref) => {
    return (React.createElement(DismissableLayer, { asChild: true, onDismiss: onClose, safeZone: { anchor: safeZoneAnchor } },
        React.createElement(Floating.Content, { ref: ref, align: "start", side: "bottom", fallbackPlacements: [], sideOffset: 8, className: "aksel-property-filter__popup" },
            React.createElement("div", { className: "aksel-property-filter__popup-inner" },
                React.createElement(Listbox.Options, null, options.map((group) => (React.createElement(Listbox.Group, { key: group.label, label: group.label }, group.options.map((item) => (React.createElement(AutoSuggestOption, { key: item.value, item: item, onSelect: onSelect, hasVirtualFocus: focusedValue === item.value, autoSuggestValue: autoSuggestValue })))))))))));
});
const AutoSuggestOption = React.memo(({ item, onSelect, hasVirtualFocus, autoSuggestValue, }) => (React.createElement(Listbox.Option, { id: item.value, onClick: () => onSelect(item), hasVirtualFocus: hasVirtualFocus, "aria-selected": false },
    React.createElement(VStack, { gap: "space-0" },
        React.createElement(BodyShort, { as: "div", size: "small" },
            React.createElement(HighlightText, { text: item.label, highlightText: autoSuggestValue })),
        item.description && React.createElement(Detail, { as: "div" }, item.description)))));
function HighlightText({ text, highlightText, }) {
    if (!text || !highlightText) {
        return React.createElement("span", null, text);
    }
    if (text === highlightText) {
        return React.createElement(Highlight, { text: text });
    }
    const { noMatches, matches } = highlightSplit(text, highlightText);
    const highlighted = [];
    noMatches.forEach((noMatch, idx) => {
        highlighted.push(React.createElement("span", { key: `noMatch-${idx}` }, noMatch));
        if (matches && idx < matches.length) {
            highlighted.push(React.createElement(Highlight, { key: `match-${idx}`, text: matches[idx] }));
        }
    });
    return React.createElement("span", null, highlighted);
}
function Highlight({ text }) {
    return React.createElement("mark", { className: "aksel-listbox__highlight" }, text);
}
function highlightSplit(text, highlightText) {
    /* Skip loooong texts */
    if (highlightText.length > 1000) {
        return { noMatches: [text], matches: null };
    }
    /* Case insensitive filtering */
    const filteringPattern = highlightText.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&");
    const regexp = new RegExp(filteringPattern, "gi");
    const noMatches = text.split(regexp);
    const matches = text.match(regexp);
    return { noMatches, matches };
}
export { AutoSuggest };
//# sourceMappingURL=AutoSuggest.js.map