var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
/* eslint-disable no-use-before-define */
import React, { useCallback, useEffect, useState } from 'react';
import { TextField, makeStyles, Popper } from '@material-ui/core';
import Autocomplete from '@material-ui/lab/Autocomplete';
import clsx from 'clsx';
const useStyles = makeStyles((theme) => ({
    formTextInput: {
        fontSize: 14
    },
    labelRoot: {
        fontSize: 14
    }
}));
const AutoCompletePopper = (props) => {
    return React.createElement(Popper, Object.assign({}, props, { placement: "bottom-start" }));
};
export const FluentTextFieldAutoComplete = (props) => {
    const { label, placeholder, options, textFieldProps, disabled, onChange: onChangeProp, value, optionKey, additionalOnChangeAction, classes: classProps, variant = 'outlined', inputProps, inputPropClasses, customPopper, disableClearable = false, defaultValue, additionalOptionKey, isMultiple = false, limitTags, renderTags, optionLabelDisplayFunction = (option) => option, groupBy = null, size = 'medium', id, udprecordid, freeSolo = false, formatUserInputValue, filterOptions: filterOptionsProp } = props, other = __rest(props, ["label", "placeholder", "options", "textFieldProps", "disabled", "onChange", "value", "optionKey", "additionalOnChangeAction", "classes", "variant", "inputProps", "inputPropClasses", "customPopper", "disableClearable", "defaultValue", "additionalOptionKey", "isMultiple", "limitTags", "renderTags", "optionLabelDisplayFunction", "groupBy", "size", "id", "udprecordid", "freeSolo", "formatUserInputValue", "filterOptions"]);
    const classes = useStyles();
    const { autocompleteRoot } = classProps || {};
    const [inputValue, setInputValue] = useState('');
    const shouldControlInputValue = freeSolo;
    const autoCompleteId = id;
    const getOptionLabel = useCallback((option) => {
        if (!option)
            return '';
        if (optionKey && typeof option === 'object') {
            return `${optionLabelDisplayFunction(option[optionKey])}${additionalOptionKey ? ` - (${option[additionalOptionKey]})` : ''}`;
        }
        return optionLabelDisplayFunction(option) || '';
    }, [optionKey, additionalOptionKey, optionLabelDisplayFunction]);
    const formatRawInput = useCallback((raw) => (formatUserInputValue ? formatUserInputValue(raw) : raw), [formatUserInputValue]);
    const getComparableLabel = useCallback((option) => {
        if (!option)
            return '';
        if (typeof option === 'string')
            return option;
        return getOptionLabel(option);
    }, [getOptionLabel]);
    const normalizeFilterValue = useCallback((value) => `${value !== null && value !== void 0 ? value : ''}`.toLowerCase().trim(), []);
    const defaultFilterOptions = useCallback((optionList) => {
        const input = normalizeFilterValue(inputValue);
        if (!input)
            return optionList;
        return optionList.filter((option) => normalizeFilterValue(getComparableLabel(option)).includes(input));
    }, [getComparableLabel, normalizeFilterValue, inputValue]);
    const hasMatchingValue = useCallback((values, candidate) => {
        if (!Array.isArray(values) ||
            candidate === null ||
            candidate === undefined)
            return false;
        const candidateLabel = getComparableLabel(candidate);
        return values.some((item) => {
            if (item === candidate)
                return true;
            if (optionKey &&
                typeof item === 'object' &&
                typeof candidate === 'object') {
                const itemKey = item === null || item === void 0 ? void 0 : item[optionKey];
                const candidateKey = candidate === null || candidate === void 0 ? void 0 : candidate[optionKey];
                if (itemKey !== undefined && candidateKey !== undefined) {
                    return itemKey === candidateKey;
                }
            }
            if (optionKey &&
                typeof item === 'object' &&
                typeof candidate === 'string') {
                const itemKey = item === null || item === void 0 ? void 0 : item[optionKey];
                if (itemKey !== undefined)
                    return `${itemKey}` === candidate;
            }
            if (optionKey &&
                typeof candidate === 'object' &&
                typeof item === 'string') {
                const candidateKey = candidate === null || candidate === void 0 ? void 0 : candidate[optionKey];
                if (candidateKey !== undefined)
                    return `${candidateKey}` === item;
            }
            return getComparableLabel(item) === candidateLabel;
        });
    }, [optionKey, getComparableLabel]);
    const commitFreeSoloMultiple = useCallback(() => {
        if (!freeSolo || !isMultiple)
            return false;
        const raw = (inputValue || '').trim();
        if (!raw)
            return false;
        const formatted = formatRawInput(raw);
        if (formatted === '' || formatted === null || formatted === undefined) {
            setInputValue('');
            return false;
        }
        const currentValues = Array.isArray(value) ? value : [];
        if (hasMatchingValue(currentValues, formatted)) {
            setInputValue('');
            return false;
        }
        const nextValues = [...currentValues, formatted];
        if (additionalOnChangeAction)
            additionalOnChangeAction(nextValues);
        onChangeProp === null || onChangeProp === void 0 ? void 0 : onChangeProp(nextValues);
        setInputValue('');
        return true;
    }, [
        freeSolo,
        isMultiple,
        inputValue,
        formatRawInput,
        value,
        hasMatchingValue,
        additionalOnChangeAction,
        onChangeProp
    ]);
    const onChange = useCallback((e, nextValue, reason) => {
        let resolvedValue = nextValue;
        if (freeSolo && isMultiple && reason === 'create-option') {
            const values = Array.isArray(nextValue) ? [...nextValue] : [];
            const raw = values[values.length - 1];
            if (typeof raw === 'string') {
                const trimmed = raw.trim();
                values.pop();
                if (trimmed) {
                    const formatted = formatRawInput(trimmed);
                    if (formatted !== '' &&
                        formatted !== null &&
                        formatted !== undefined &&
                        !hasMatchingValue(values, formatted)) {
                        values.push(formatted);
                    }
                }
                setInputValue('');
                resolvedValue = values;
            }
        }
        if (freeSolo &&
            isMultiple &&
            (reason === 'select-option' || reason === 'clear')) {
            setInputValue('');
        }
        if (additionalOnChangeAction) {
            additionalOnChangeAction(resolvedValue);
        }
        return onChangeProp === null || onChangeProp === void 0 ? void 0 : onChangeProp(resolvedValue);
    }, [
        additionalOnChangeAction,
        freeSolo,
        isMultiple,
        formatRawInput,
        hasMatchingValue,
        onChangeProp
    ]);
    const handleInputChange = useCallback((e, newInputValue, reason) => {
        const nextValue = newInputValue !== null && newInputValue !== void 0 ? newInputValue : '';
        if (freeSolo && isMultiple && reason === 'reset') {
            return;
        }
        setInputValue(nextValue);
        if (!freeSolo || isMultiple)
            return;
        if (reason === 'input' || reason === 'clear') {
            if (additionalOnChangeAction)
                additionalOnChangeAction(nextValue);
            onChangeProp === null || onChangeProp === void 0 ? void 0 : onChangeProp(nextValue);
        }
    }, [freeSolo, isMultiple, additionalOnChangeAction, onChangeProp]);
    const handleClose = useCallback((event, reason) => {
        if (!freeSolo)
            return;
        const raw = (inputValue || '').trim();
        if (!raw)
            return;
        if (isMultiple) {
            if (reason !== 'blur')
                return;
            commitFreeSoloMultiple();
            return;
        }
        if (value && typeof value === 'object')
            return;
        if (reason === 'blur' ||
            reason === 'enter' ||
            reason === 'create-option') {
            const updatedValue = formatRawInput(raw);
            if (additionalOnChangeAction)
                additionalOnChangeAction(updatedValue);
            onChangeProp === null || onChangeProp === void 0 ? void 0 : onChangeProp(updatedValue);
        }
    }, [
        freeSolo,
        isMultiple,
        value,
        inputValue,
        formatRawInput,
        commitFreeSoloMultiple,
        additionalOnChangeAction,
        onChangeProp
    ]);
    useEffect(() => {
        if (!freeSolo || isMultiple)
            return;
        if (value === null || value === undefined) {
            if (inputValue !== '')
                setInputValue('');
            return;
        }
        const nextValue = typeof value === 'string' ? value : getOptionLabel(value);
        if (nextValue !== inputValue) {
            setInputValue(nextValue || '');
        }
    }, [freeSolo, isMultiple, value, getOptionLabel, inputValue]);
    return (React.createElement(Autocomplete, { id: autoCompleteId, multiple: isMultiple, limitTags: limitTags, disabled: disabled, options: options || [], getOptionLabel: getOptionLabel, getOptionSelected: (option, val) => optionKey ? option[optionKey] === val[optionKey] : option === val, groupBy: groupBy, onChange: onChange, inputValue: shouldControlInputValue ? inputValue : undefined, onInputChange: shouldControlInputValue ? handleInputChange : undefined, onClose: handleClose, value: value || (isMultiple ? [] : null), className: autocompleteRoot, classes: {
            root: classProps === null || classProps === void 0 ? void 0 : classProps.formControl
        }, PopperComponent: customPopper || AutoCompletePopper, disableClearable: disableClearable, defaultValue: defaultValue, size: size, renderInput: (params) => (React.createElement(TextField, Object.assign({}, textFieldProps, params, other, { inputProps: Object.assign(Object.assign({}, params.inputProps), { udprecordid: udprecordid, onKeyDown: (event) => {
                    var _a, _b, _c;
                    (_b = (_a = params.inputProps) === null || _a === void 0 ? void 0 : _a.onKeyDown) === null || _b === void 0 ? void 0 : _b.call(_a, event);
                    (_c = textFieldProps === null || textFieldProps === void 0 ? void 0 : textFieldProps.onKeyDown) === null || _c === void 0 ? void 0 : _c.call(textFieldProps, event);
                    if (event.defaultMuiPrevented)
                        return;
                    if (!freeSolo || !isMultiple)
                        return;
                    if (event.key !== 'Enter')
                        return;
                    const didCommit = commitFreeSoloMultiple();
                    if (didCommit) {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                } }), label: label, margin: "dense", variant: variant, placeholder: placeholder, size: "small", InputProps: Object.assign(Object.assign(Object.assign({}, params.InputProps), inputProps), { classes: {
                    root: classProps === null || classProps === void 0 ? void 0 : classProps.inputPropRoot,
                    input: clsx(classes.formTextInput, classProps === null || classProps === void 0 ? void 0 : classProps.inputPropInput)
                } }), InputLabelProps: {
                classes: {
                    root: clsx(classes.labelRoot, classProps === null || classProps === void 0 ? void 0 : classProps.formLabelRoot)
                }
            } }))), renderTags: renderTags, filterOptions: filterOptionsProp || (freeSolo ? defaultFilterOptions : undefined), freeSolo: freeSolo }));
};
//# sourceMappingURL=FluentTextFieldAutoComplete.js.map