'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var _tslib = require('../../../_virtual/_tslib.js');
var React = require('react');
var reactPopper = require('react-popper');
var useClickOutside = require('../../../hooks/useClickOutside.js');
var useDebounce = require('../../../hooks/useDebounce.js');
var useKeyPress = require('../../../hooks/useKeyPress.js');
var AlertCircle = require('../../../icons/AlertCircle.js');
var Close = require('../../../icons/Close.js');
var Search = require('../../../icons/Search.js');
var index = require('../../../utils/index.js');
var styles$2 = require('../dropdown/styles.js');
var styles = require('../styles.js');
var SearchOptions = require('./components/SearchOptions.js');
var styles$1 = require('./styles.js');
var utils = require('./utils.js');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var React__default = /*#__PURE__*/_interopDefaultLegacy(React);

function SearchableDropdown(_a) {
    var _b;
    var { variant, id, className, name, label, required, optionalText, errorText, assistText, value, placeholder, width, hasError = false, options, debounceDelay = 500, noResultsText, onChange, onOpen, onClose, onFocus, onBlur, onTextChange, disabled = false, maxHeight = 300, touched } = _a, props = _tslib.__rest(_a, ["variant", "id", "className", "name", "label", "required", "optionalText", "errorText", "assistText", "value", "placeholder", "width", "hasError", "options", "debounceDelay", "noResultsText", "onChange", "onOpen", "onClose", "onFocus", "onBlur", "onTextChange", "disabled", "maxHeight", "touched"]);
    const inputRef = React.useRef(null);
    const [referenceElement, setReferenceElement] = React.useState(null);
    const [popperElement, setPopperElement] = React.useState(null);
    const [popperWidth, setPopperWidth] = React.useState(0);
    const [visible, setVisibility] = React.useState(false);
    const { containerRef } = useClickOutside.useOnClickOutside(() => setVisibility(false));
    const [focusElement, setFocusElement] = React.useState(-1);
    const [searchValue, setSearchValue] = React.useState('');
    const [selectedOption, setSelectedOption] = React.useState(value);
    const [filteredOptions, setFilteredOptions] = React.useState(options);
    const debouncedValue = useDebounce.useDebounce(searchValue, debounceDelay);
    const arrowDownPressed = useKeyPress.useKeyPress('ArrowDown', inputRef);
    const arrowUpPressed = useKeyPress.useKeyPress('ArrowUp', inputRef);
    const enterPressed = useKeyPress.useKeyPress('Enter', inputRef);
    const [showError, setShowError] = React.useState(false);
    React.useEffect(() => {
        const composeError = typeof touched === 'undefined' ? hasError : hasError && touched;
        setShowError(composeError);
    }, [hasError, touched]);
    const { styles: styles$3, attributes } = reactPopper.usePopper(referenceElement, popperElement, utils.popperOptions);
    const openPopper = () => {
        if (disabled)
            return;
        setVisibility(true);
        onOpen && onOpen();
    };
    const closePopper = () => {
        if (disabled)
            return;
        setVisibility(false);
        onClose && onClose();
    };
    const handleOptionChange = (opt) => {
        if (opt.label && !opt.isDisabled && filteredOptions.length > 0) {
            closePopper();
            setSearchValue(opt.label);
            setSelectedOption(opt);
            onChange(opt);
            setFocusElement(-1);
        }
    };
    const handleInputChange = (event) => {
        if (!visible)
            openPopper();
        const value = event.target.value;
        if (value === '')
            setFilteredOptions(options);
        setSearchValue(value);
        onTextChange && onTextChange(value);
    };
    const handleInputFocus = () => {
        if (!visible && searchValue === '')
            openPopper();
        onFocus && onFocus();
    };
    const handleClear = (event) => {
        if (!disabled) {
            event.preventDefault();
            setFilteredOptions(options);
            setSearchValue('');
            onChange(null);
            setSelectedOption(null);
            openPopper();
        }
    };
    const handleBlur = () => {
        if (searchValue !== '' && filteredOptions.length >= 1 && !selectedOption) {
            setSearchValue(filteredOptions[0].label);
        }
        else if (!selectedOption) {
            setSearchValue('');
        }
        onBlur && onBlur();
    };
    const showClearIcon = () => {
        return searchValue.length > 0 || selectedOption !== null;
    };
    React.useEffect(() => {
        value && setSearchValue(value.label);
    }, [value]);
    React.useEffect(() => {
        if (containerRef && containerRef.current) {
            setPopperWidth(containerRef.current.clientWidth);
        }
    }, [(_b = containerRef.current) === null || _b === void 0 ? void 0 : _b.clientWidth]);
    React.useEffect(() => {
        if (debouncedValue && debouncedValue !== '') {
            const filtered = options.filter((opt) => {
                if (debouncedValue.length > 1)
                    return opt.label.toLowerCase().includes(debouncedValue.toLowerCase());
                return opt.label.toLowerCase().startsWith(debouncedValue.toLowerCase());
            });
            setFilteredOptions(filtered);
            setFocusElement(0);
        }
        else {
            setFilteredOptions(options);
        }
    }, [debouncedValue, options]);
    React.useEffect(() => {
        if (filteredOptions.length > 0) {
            if (arrowDownPressed) {
                if (focusElement < filteredOptions.length - 1) {
                    setFocusElement(focusElement + 1);
                }
            }
            if (arrowUpPressed) {
                if (focusElement >= 1) {
                    setFocusElement(focusElement - 1);
                }
            }
            if (enterPressed && focusElement >= 0) {
                const opt = filteredOptions[focusElement];
                handleOptionChange(opt);
            }
        }
    }, [arrowDownPressed, arrowUpPressed, enterPressed]);
    const appendTestId = index.getId(props['data-testid']);
    return (React__default['default'].createElement(styles.Wrapper, { className: className, "data-testid": appendTestId('searchable-dropdown'), "data-trackid": props['data-trackid'], "aria-label": props['aria-label'] || label, ref: containerRef, onClick: () => { var _a; return inputRef && ((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus()); }, width: width },
        React__default['default'].createElement(styles.LabelWrapper, { disabled: disabled, hasLabel: Boolean(label === null || label === void 0 ? void 0 : label.length) },
            label && (React__default['default'].createElement(styles.Label, { htmlFor: id || `input-${name}`, disabled: disabled }, label)),
            !required && React__default['default'].createElement(styles.Text, null, optionalText)),
        React__default['default'].createElement(styles.Border, { disabled: disabled, hasError: showError, "aria-haspopup": "true", "aria-expanded": visible, ref: setReferenceElement },
            React__default['default'].createElement(styles$1.IconWrapper, null,
                React__default['default'].createElement(Search['default'], { width: 24, height: 24 })),
            React__default['default'].createElement(styles$1.InputWrapper, null,
                React__default['default'].createElement(styles$1.Input, { id: id || `input-${name}`, ref: inputRef, type: "text", "data-testid": appendTestId(), variant: variant, disabled: disabled, placeholder: placeholder, "aria-haspopup": "true", autoComplete: "off", value: searchValue, onChange: handleInputChange, onBlur: handleBlur, onFocus: handleInputFocus })),
            showClearIcon() && (React__default['default'].createElement(styles$1.CloseWrapper, { disabled: disabled, onMouseDown: handleClear },
                React__default['default'].createElement(Close['default'], { width: 24, height: 24 })))),
        visible && !disabled && (React__default['default'].createElement(styles$2.OptionsPopper, Object.assign({ role: "listbox", "data-testid": appendTestId('popper'), ref: setPopperElement, width: popperWidth, maxHeight: maxHeight, style: styles$3.popper }, attributes.popper),
            React__default['default'].createElement(SearchOptions.SearchOptions, { searchOptions: filteredOptions, noResultsText: noResultsText, value: searchValue === '' ? searchValue : debouncedValue, focusElement: focusElement, setFocusElement: setFocusElement, onClick: handleOptionChange }))),
        React__default['default'].createElement(styles.SupportingText, null,
            Boolean(errorText) && showError && !disabled && (React__default['default'].createElement(styles.ErrorMessage, null,
                React__default['default'].createElement(AlertCircle['default'], null),
                errorText)),
            !showError &&
                (typeof assistText === 'string' ? (React__default['default'].createElement(styles.AssistMessage, null, assistText)) : (assistText)))));
}

exports.SearchableDropdown = SearchableDropdown;
