/*!
 * Copyright (c) Microsoft. All rights reserved.
 * Licensed under the MIT license. See LICENSE file in the project.
 */ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { BooleanComparisonOperator, DataType, DateComparisonOperator, FilterCompareType, NumericComparisonOperator, StringComparisonOperator } from '@datashaper/schema';
import { EnumDropdown } from '@essex/components';
import { IconButton, SpinButton } from '@fluentui/react';
import { memo, useCallback, useMemo, useState } from 'react';
import { CalendarPicker, ColumnCriteriaCombobox } from '../../controls/index.js';
import { useSimpleDropdownOptions, useTableColumnNames } from '../../hooks/index.js';
import { InputExplainer, LeftAlignedRow } from '../../styles.js';
import { useColumnTyping, useIsEmpty } from './FilterFunction.hooks.js';
import { BooleanToggle, Container, FilterContainer, Input, InputLabel, leftStyles, OrLabel, spinStyles, TextValue } from './FilterFunction.styles.js';
/**
 * Just the comparison logic/ops for a filter.
 * Input table and source column is expected to be edited elsewhere and configured as the step input.
 * This is split out from FilterInputs to allow just the comparison logic to be reused elsewhere.
 */ export const FilterFunction = /*#__PURE__*/ memo(function FilterFunction({ table , column , criterion , onChange  }) {
    const handleOpChange = useCallback((_e, opt)=>{
        onChange && onChange({
            ...criterion,
            operator: opt?.key
        });
    }, [
        criterion,
        onChange
    ]);
    const onSelectDate = useCallback((date)=>{
        const update = {
            ...criterion,
            type: FilterCompareType.Value,
            value: date
        };
        onChange && onChange(update);
        setCleanLabel(false);
    }, [
        criterion,
        onChange
    ]);
    const handleDateComboBoxChange = useCallback((_e, option, _index, value)=>{
        const update = {
            ...criterion,
            type: FilterCompareType.Column,
            value: option ? option.key : value
        };
        onChange?.(update);
        setCleanLabel(true);
    }, [
        criterion,
        onChange
    ]);
    const handleComboBoxChange = useCallback((_e, option, _index, value)=>{
        const update = {
            ...criterion,
            type: FilterCompareType.Column,
            value: option ? option.key : value
        };
        onChange?.(update);
    }, [
        criterion,
        onChange
    ]);
    const onChangeTextFieldValue = useCallback((_event, newValue)=>{
        const update = {
            ...criterion,
            type: FilterCompareType.Value,
            value: newValue
        };
        onChange?.(update);
    }, [
        criterion,
        onChange
    ]);
    const spinButtonOnChange = useCallback((_event, newValue)=>{
        if (newValue !== undefined) {
            const update = {
                ...criterion,
                type: FilterCompareType.Value,
                value: newValue
            };
            onChange?.(update);
        }
    }, [
        criterion,
        onChange
    ]);
    const onToggleChange = (_ev, checked)=>{
        const update = {
            ...criterion,
            type: FilterCompareType.Value,
            value: checked
        };
        onChange?.(update);
    };
    const { type , columnFilter  } = useColumnTyping(table, column);
    const [cleanLabel, setCleanLabel] = useState(false);
    const operatorDropdown = useMemo(()=>{
        const shared = {
            label: '',
            placeholder: 'Choose',
            selectedKey: criterion.operator,
            onChange: handleOpChange,
            styles: leftStyles
        };
        if (column) {
            if (type === DataType.String) {
                return /*#__PURE__*/ _jsx(EnumDropdown, {
                    enumeration: StringComparisonOperator,
                    ...shared
                });
            } else if (type === DataType.Boolean) {
                return /*#__PURE__*/ _jsx(EnumDropdown, {
                    enumeration: BooleanComparisonOperator,
                    ...shared
                });
            } else if (type === DataType.Date) {
                return /*#__PURE__*/ _jsx(EnumDropdown, {
                    enumeration: DateComparisonOperator,
                    ...shared
                });
            }
        }
        // map to nicer "math like" terse labels for numeric operations
        // (the default will use the friendly enum keys)
        const labels = {
            '=': '=',
            '!=': '!=',
            '<': '<',
            '<=': '<=',
            '>': '>',
            '>=': '>='
        };
        return /*#__PURE__*/ _jsx(EnumDropdown, {
            enumeration: NumericComparisonOperator,
            ...shared,
            labels: labels
        });
    }, [
        type,
        column,
        criterion,
        handleOpChange
    ]);
    const isEmpty = useIsEmpty(criterion);
    const handleDeleteClick = useCallback(()=>onChange?.(), [
        onChange
    ]);
    const columns = useTableColumnNames(table, columnFilter);
    const columnOptions = useSimpleDropdownOptions(columns);
    return /*#__PURE__*/ _jsxs(Container, {
        children: [
            /*#__PURE__*/ _jsxs(LeftAlignedRow, {
                children: [
                    operatorDropdown,
                    /*#__PURE__*/ _jsx(IconButton, {
                        title: 'Remove this criterion',
                        iconProps: deleteIconProps,
                        onClick: handleDeleteClick
                    })
                ]
            }),
            /*#__PURE__*/ _jsxs(FilterContainer, {
                children: [
                    /*#__PURE__*/ _jsxs(Input, {
                        children: [
                            /*#__PURE__*/ _jsx(InputLabel, {
                                children: "value"
                            }),
                            type === DataType.Date ? /*#__PURE__*/ _jsx(CalendarPicker, {
                                onSelectDate: onSelectDate,
                                disabled: isEmpty,
                                cleanLabel: cleanLabel
                            }) : null,
                            type === DataType.String ? /*#__PURE__*/ _jsx(TextValue, {
                                value: criterion.value,
                                onChange: onChangeTextFieldValue,
                                disabled: isEmpty
                            }) : null,
                            type === DataType.Number ? /*#__PURE__*/ _jsx(SpinButton, {
                                min: 0,
                                step: 1,
                                value: criterion.value,
                                styles: spinStyles,
                                disabled: isEmpty,
                                onChange: spinButtonOnChange
                            }) : null,
                            type === DataType.Boolean ? /*#__PURE__*/ _jsx(BooleanToggle, {
                                defaultChecked: true,
                                onText: "True",
                                offText: "False",
                                onChange: onToggleChange,
                                disabled: isEmpty
                            }) : null
                        ]
                    }),
                    /*#__PURE__*/ _jsx(OrLabel, {
                        children: "or"
                    }),
                    /*#__PURE__*/ _jsxs(Input, {
                        children: [
                            /*#__PURE__*/ _jsx(InputLabel, {
                                children: "column"
                            }),
                            type === DataType.Date ? /*#__PURE__*/ _jsx(ColumnCriteriaCombobox, {
                                options: columnOptions,
                                onChange: handleDateComboBoxChange,
                                disabled: isEmpty
                            }) : /*#__PURE__*/ _jsx(ColumnCriteriaCombobox, {
                                options: columnOptions,
                                onChange: handleComboBoxChange,
                                disabled: isEmpty
                            })
                        ]
                    })
                ]
            }),
            type === DataType.String ? /*#__PURE__*/ _jsx(InputExplainer, {
                children: "String comparisons are not case-sensitive"
            }) : null
        ]
    });
});
const deleteIconProps = {
    iconName: 'Delete'
};
