import * as React from 'react';
import { CheckBox } from '../../../../components/CheckBox';
import AdaptableInput from '../../AdaptableInput';
import { AdaptableDateInlineInput } from '../../AdaptableInput/AdaptableDateInlineInput';
import { PermittedValuesSelector } from '../../Selectors/PermittedValuesSelector';
import { useAdaptable } from '../../../AdaptableContext';
import debounce from 'lodash/debounce';
import { useCallback } from 'react';
function debounceOrImmediate(fn, time) {
    return time && time > 0 ? debounce(fn, time) : fn;
}
export const ColumnFilterInput = (props) => {
    const { type, value, onChange: onChangeProp, onClear: onClearProp, disabled, onKeyDown, filterType, usePrimitiveInputs = true, columnId, } = props;
    const [liveValue, setLiveValue] = React.useState(value);
    const [hasFocus, setHasFocus] = React.useState(false);
    const onFocus = useCallback(() => {
        setHasFocus(true);
    }, []);
    const onBlur = useCallback(() => {
        setHasFocus(false);
    }, []);
    React.useEffect(() => {
        // only update if the input is not focused
        // eg: value coming from a sidebar filter
        // should be reflected in the input
        // but if the input is focused, it means the user is typing
        // so we don't want to update the input value from the outside (from state)
        // but we leave liveValue as is in the local component state
        if (!hasFocus) {
            setLiveValue(value);
        }
    }, [value, hasFocus]);
    const adaptable = useAdaptable();
    const filterOptions = adaptable.api.optionsApi.getFilterOptions();
    const debounceTime = filterOptions.columnFilterOptions.quickFilterDebounce;
    const showDatePicker = filterOptions.showDatePicker;
    const onChange = React.useMemo(() => {
        return debounceOrImmediate((value) => {
            //@ts-ignore
            onChangeProp(value);
        }, debounceTime);
    }, [onChangeProp, debounceTime]);
    // the onClear needs to have the same debounce time as the onChange
    const onClear = React.useMemo(() => {
        return debounceOrImmediate(() => {
            onClearProp();
        }, debounceTime);
    }, [onClearProp, debounceTime]);
    if (type === 'boolean') {
        return (React.createElement(CheckBox, { disabled: disabled, onFocus: onFocus, onBlur: onBlur, checked: value === 'checked'
                ? true
                : value === 'unchecked'
                    ? false
                    : // 'all'
                        null, onChange: (checked) => {
                // sequence: 'checked' -> 'unchecked' -> 'all' -> 'checked'
                const newCheckedValue = value === 'unchecked' && checked === true
                    ? 'all'
                    : checked === true
                        ? 'checked'
                        : 'unchecked';
                onChange(newCheckedValue);
            } }));
    }
    const onKeyDownCapture = (e) => {
        if (e.nativeEvent.key === 'Escape') {
            e.nativeEvent.preventDefault();
            e.nativeEvent.stopPropagation();
            onClear();
            setLiveValue('');
        }
    };
    if (type === 'date' && !showDatePicker) {
        return (React.createElement(AdaptableDateInlineInput, { "data-name": "floating-filter-input", value: liveValue, disabled: disabled, onFocus: onFocus, onBlur: onBlur, className: "twa:border-none twa:pr-0", onKeyDownCapture: onKeyDownCapture, onChange: (value) => {
                onChange(value);
                setLiveValue(value);
            } }));
    }
    if (usePrimitiveInputs === false && (type === 'number' || type === 'text')) {
        // we use the permitted values selector
        return (React.createElement(PermittedValuesSelector, { allowNewValues: true, searchable: 'inline', value: liveValue, columnId: columnId, onFocus: onFocus, onBlur: onBlur, onChange: (value) => {
                if (value == undefined) {
                    onClear();
                    setLiveValue('');
                }
                else {
                    // @ts-ignore
                    onChange(value);
                    setLiveValue(value);
                }
            } }));
    }
    return (React.createElement(AdaptableInput, { style: filterType === 'floating'
            ? {
                width: '100%',
                padding: 'var(--ab-base-space)',
                borderRadius: 0,
                border: 'none',
            }
            : {}, "data-name": "floating-filter-input", onFocus: onFocus, onBlur: onBlur, disabled: disabled, type: type === 'number' ? 'text' : type, 
        // autoFocus has to be FALSE because if the input receives focus in the init phase,
        // it may scroll the AG Grid header viewport into view and de-synchronize it (relative to the content viewport)
        autoFocus: false, value: liveValue ?? '', onKeyDown: onKeyDown, showClearButton: false, className: "twa:flex-1", onChange: (e) => {
            const prevValue = `${liveValue}`;
            const value = e.target.value;
            if (value) {
                if (type === 'number') {
                    let numericValue = parseFloat(value);
                    let liveValue = numericValue;
                    if (isNaN(numericValue)) {
                        numericValue = null;
                        liveValue = null;
                        if (value === '-') {
                            liveValue = value;
                        }
                    }
                    else {
                        const prevValueHasSeparator = prevValue.includes('.');
                        const newValueEndsWithSeparator = value.endsWith('.');
                        const newValueStartsWithSeparator = value.startsWith('.');
                        const newValueEndsWithZero = value.endsWith('0');
                        const separatorCount = (value.match(/[.,]/g) || []).length;
                        if (prevValueHasSeparator && separatorCount > 1) {
                            // not a valid number
                            return;
                        }
                        if (newValueEndsWithSeparator) {
                            const valueWithoutLastChar = value.slice(0, -1);
                            if (numericValue === parseFloat(valueWithoutLastChar)) {
                                liveValue = value;
                            }
                        }
                        if (newValueEndsWithZero) {
                            liveValue = value;
                        }
                        if (newValueStartsWithSeparator) {
                            if (numericValue === parseFloat('0' + value)) {
                                liveValue = value;
                            }
                        }
                    }
                    onChange(numericValue);
                    setLiveValue(liveValue);
                }
                else {
                    onChange(value);
                    setLiveValue(value);
                }
            }
            else {
                onClear();
                setLiveValue('');
            }
        }, onKeyDownCapture: onKeyDownCapture }));
};
