"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const react_1 = tslib_1.__importDefault(require("react"));
const react_core_1 = require("@patternfly/react-core");
const times_icon_1 = tslib_1.__importDefault(require("@patternfly/react-icons/dist/esm/icons/times-icon"));
const formik_1 = require("formik");
const lodash_es_1 = require("lodash-es");
const NO_RESULTS = 'no_results';
const createItemId = (val) => `select-multi-typeahead-${val.replace(' ', '-')}`;
const SelectFieldWithSearch = ({ name, label, isRequired, selectOptions, filterValue, setFilterValue, isMultiSelect = false, isLoading = false, placeholder, helperText, }) => {
    const [isOpen, setIsOpen] = react_1.default.useState(false);
    const [{ value }, , { setValue }] = (0, formik_1.useField)(name);
    const [focusedItemIndex, setFocusedItemIndex] = react_1.default.useState(null);
    const [activeItemId, setActiveItemId] = react_1.default.useState(null);
    const textInputRef = react_1.default.useRef();
    const setActiveAndFocusedItem = (itemIndex) => {
        setFocusedItemIndex(itemIndex);
        const focusedItem = selectOptions[itemIndex];
        setActiveItemId(createItemId(focusedItem.value));
    };
    const resetActiveAndFocusedItem = () => {
        setFocusedItemIndex(null);
        setActiveItemId(null);
    };
    const closeMenu = () => {
        setIsOpen(false);
        resetActiveAndFocusedItem();
    };
    const onInputClick = () => {
        if (!isOpen) {
            setIsOpen(true);
        }
        else if (!filterValue) {
            closeMenu();
        }
    };
    const handleMenuArrowKeys = (key) => {
        let indexToFocus = 0;
        if (!isOpen) {
            setIsOpen(true);
        }
        if (selectOptions.every((option) => option.isDisabled)) {
            return;
        }
        if (key === 'ArrowUp') {
            // When no index is set or at the first index, focus to the last, otherwise decrement focus index
            if (focusedItemIndex === null || focusedItemIndex === 0) {
                indexToFocus = selectOptions.length - 1;
            }
            else {
                indexToFocus = focusedItemIndex - 1;
            }
            // Skip disabled options
            while (selectOptions[indexToFocus].isDisabled) {
                indexToFocus--;
                if (indexToFocus === -1) {
                    indexToFocus = selectOptions.length - 1;
                }
            }
        }
        if (key === 'ArrowDown') {
            // When no index is set or at the last index, focus to the first, otherwise increment focus index
            if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) {
                indexToFocus = 0;
            }
            else {
                indexToFocus = focusedItemIndex + 1;
            }
            // Skip disabled options
            while (selectOptions[indexToFocus].isDisabled) {
                indexToFocus++;
                if (indexToFocus === selectOptions.length) {
                    indexToFocus = 0;
                }
            }
        }
        setActiveAndFocusedItem(indexToFocus);
    };
    const onInputKeyDown = (event) => {
        const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;
        switch (event.key) {
            case 'Enter':
                if (isOpen &&
                    focusedItem &&
                    focusedItem.value !== NO_RESULTS &&
                    !focusedItem.isAriaDisabled) {
                    onSelect(focusedItem.value);
                }
                if (!isOpen) {
                    setIsOpen(true);
                }
                break;
            case 'ArrowUp':
            case 'ArrowDown':
                event.preventDefault();
                handleMenuArrowKeys(event.key);
                break;
        }
    };
    const onToggleClick = () => {
        var _a;
        setIsOpen(!isOpen);
        (_a = textInputRef === null || textInputRef === void 0 ? void 0 : textInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
    };
    const onTextInputChange = (_event, value) => {
        setFilterValue(value);
        resetActiveAndFocusedItem();
    };
    const onSelect = react_1.default.useCallback((val) => {
        var _a, _b;
        if (val && val !== NO_RESULTS) {
            if (isMultiSelect && Array.isArray(value)) {
                setValue(value.some((v) => (0, lodash_es_1.isEqual)(v, val))
                    ? value.filter((v) => !(0, lodash_es_1.isEqual)(v, val))
                    : [...value, val]);
            }
            else {
                setValue(val);
                setFilterValue((_a = selectOptions.find((option) => option.value === val)) === null || _a === void 0 ? void 0 : _a.children);
            }
        }
        (_b = textInputRef.current) === null || _b === void 0 ? void 0 : _b.focus();
    }, [isMultiSelect, setValue, setFilterValue, selectOptions, value]);
    const onClearButtonClick = () => {
        var _a;
        setFilterValue('');
        resetActiveAndFocusedItem();
        (_a = textInputRef === null || textInputRef === void 0 ? void 0 : textInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
    };
    const toggle = (toggleRef) => (react_1.default.createElement(react_core_1.MenuToggle, { variant: "typeahead", "aria-label": "Multi typeahead checkbox menu toggle", onClick: onToggleClick, innerRef: toggleRef, isExpanded: isOpen, isFullWidth: true },
        react_1.default.createElement(react_core_1.TextInputGroup, { isPlain: true },
            react_1.default.createElement(react_core_1.TextInputGroupMain, Object.assign({ isExpanded: isOpen, value: filterValue, placeholder: placeholder, onClick: onInputClick, onChange: onTextInputChange, onKeyDown: onInputKeyDown, innerRef: textInputRef, autoComplete: "off", role: "combobox", id: "typeahead-select-input", "aria-controls": "typeahead-select-listbox" }, (activeItemId && { 'aria-activedescendant': activeItemId }))),
            react_1.default.createElement(react_core_1.TextInputGroupUtilities, Object.assign({}, (!filterValue ? { style: { display: 'none' } } : {})),
                react_1.default.createElement(react_core_1.Button, { variant: "plain", onClick: onClearButtonClick, "aria-label": "Clear input value" },
                    react_1.default.createElement(times_icon_1.default, { "aria-hidden": true }))))));
    return (react_1.default.createElement(react_core_1.FormGroup, { label: label, isRequired: isRequired },
        react_1.default.createElement(react_core_1.Select, { role: "menu", id: "typeahead-select", isOpen: isOpen, selected: value, onSelect: (_event, selection) => onSelect(selection), onOpenChange: (isOpen) => {
                !isOpen && closeMenu();
            }, toggle: toggle, isScrollable: true },
            react_1.default.createElement(react_core_1.SelectList, { isAriaMultiselectable: true, id: "select-typeahead-listbox" }, isLoading ? (react_1.default.createElement(react_core_1.SelectOption, { key: 'loader' },
                react_1.default.createElement(react_core_1.Bullseye, null,
                    react_1.default.createElement(react_core_1.Spinner, { size: "lg" })))) : (selectOptions.map((option, index) => (react_1.default.createElement(react_1.default.Fragment, null,
                option.showDivider && react_1.default.createElement(react_core_1.Divider, { component: "li", key: `divider-${index}` }),
                react_1.default.createElement(react_core_1.SelectOption, Object.assign({ hasCheckbox: isMultiSelect && !option.isAriaDisabled, isSelected: isMultiSelect && Array.isArray(value)
                        ? value.some((v) => (0, lodash_es_1.isEqual)(v, option.value))
                        : value === option.value, key: `option-${index}`, isFocused: focusedItemIndex === index, ref: null }, option)))))))),
        helperText && (react_1.default.createElement(react_core_1.FormHelperText, null,
            react_1.default.createElement(react_core_1.HelperText, null,
                react_1.default.createElement(react_core_1.HelperTextItem, null, helperText))))));
};
exports.default = SelectFieldWithSearch;
//# sourceMappingURL=SelectFieldWithSearch.js.map