"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FilterFormReact = void 0;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const react_redux_1 = require("react-redux");
const LayoutRedux = tslib_1.__importStar(require("../../../Redux/ActionsReducers/LayoutRedux"));
const LayoutRedux_1 = require("../../../Redux/ActionsReducers/LayoutRedux");
const SystemRedux = tslib_1.__importStar(require("../../../Redux/ActionsReducers/SystemRedux"));
const Enums_1 = require("../../../PredefinedConfig/Common/Enums");
const ListBoxFilterForm_1 = require("./ListBoxFilterForm");
const ButtonClose_1 = require("../Buttons/ButtonClose");
const StringExtensions_1 = require("../../../Utilities/Extensions/StringExtensions");
const ButtonClear_1 = require("../Buttons/ButtonClear");
const ListBoxMenu_1 = require("./ListBoxMenu");
const FilterFormPanel_1 = require("../Panels/FilterFormPanel");
const ObjectFactory_1 = require("../../../Utilities/ObjectFactory");
const HelpBlock_1 = tslib_1.__importDefault(require("../../../components/HelpBlock"));
const rebass_1 = require("rebass");
const Radio_1 = tslib_1.__importDefault(require("../../../components/Radio"));
const Helper_1 = tslib_1.__importStar(require("../../../Utilities/Helpers/Helper"));
const AdaptableInput_1 = tslib_1.__importDefault(require("../AdaptableInput"));
const renderWithAdaptableContext_1 = require("../../renderWithAdaptableContext");
const CheckBox_1 = require("../../../components/CheckBox");
const runIfNotResolvedIn_1 = require("../../../Utilities/runIfNotResolvedIn");
const getDefaultColumnFilterPredicate_1 = require("./getDefaultColumnFilterPredicate");
const AdaptableDateInlineInput_1 = require("../AdaptableInput/AdaptableDateInlineInput");
const panelStyle = {
    width: '100%',
    minWidth: 150,
};
class FilterFormComponent extends React.Component {
    static createColumnFilterFromProps(props) {
        let existingColumnFilter = props.columnFilters.find((cf) => cf.ColumnId == props.currentColumn.columnId);
        if (!existingColumnFilter) {
            const columnFilterOptions = props.api.optionsApi.getColumnFilterOptions();
            if (columnFilterOptions.filterFormOptions.defaultFilterFormTab == 'Values') {
                return ObjectFactory_1.ObjectFactory.CreateColumnFilter(props.currentColumn.columnId, 'Values', []);
            }
            if (props.currentColumn.dataType === 'Number') {
                return ObjectFactory_1.ObjectFactory.CreateColumnFilter(props.currentColumn.columnId, (0, getDefaultColumnFilterPredicate_1.getDefaultColumnFilterPredicate)(props.currentColumn, columnFilterOptions.defaultNumericColumnFilter), ['']);
            }
            if (props.currentColumn.dataType === 'String') {
                return ObjectFactory_1.ObjectFactory.CreateColumnFilter(props.currentColumn.columnId, (0, getDefaultColumnFilterPredicate_1.getDefaultColumnFilterPredicate)(props.currentColumn, columnFilterOptions.defaultStringColumnFilter), ['']);
            }
            if (props.currentColumn.dataType === 'Date') {
                return ObjectFactory_1.ObjectFactory.CreateColumnFilter(props.currentColumn.columnId, (0, getDefaultColumnFilterPredicate_1.getDefaultColumnFilterPredicate)(props.currentColumn, columnFilterOptions.defaultDateColumnFilter), ['']);
            }
            if (props.currentColumn.dataType === 'Boolean') {
                return ObjectFactory_1.ObjectFactory.CreateColumnFilter(props.currentColumn.columnId, 'BooleanToggle', [
                    'all',
                ]);
            }
        }
        return existingColumnFilter;
    }
    static getCurrentTab(editedColumnFilter) {
        return editedColumnFilter &&
            editedColumnFilter.Predicate &&
            editedColumnFilter.Predicate.PredicateId &&
            editedColumnFilter.Predicate.PredicateId != 'Values'
            ? 'predicates'
            : 'values';
    }
    static getDerivedStateFromProps(props, state) {
        const columnFilterOptions = props.api.optionsApi.getColumnFilterOptions();
        const editedColumnFilter = columnFilterOptions.autoApplyFilter
            ? FilterFormComponent.createColumnFilterFromProps(props)
            : state.editedColumnFilter;
        let columnFilters = state.columnFilters;
        let filtersChanged = false;
        if (props.columnFilters !== columnFilters) {
            columnFilters = props.columnFilters;
            filtersChanged = true;
        }
        return {
            editedColumnFilter,
            columnFilters,
            currentTab: filtersChanged || !state.currentTab
                ? FilterFormComponent.getCurrentTab(editedColumnFilter)
                : state.currentTab,
        };
    }
    constructor(props) {
        super(props);
        this._isMounted = false;
        this.handleFilterChange = (filter) => {
            if (this.state.suppressClientSideFilter) {
                this.loadPermittedValues(filter);
            }
        };
        this._isMounted = true;
        const existingColumnFilter = FilterFormComponent.createColumnFilterFromProps(this.props);
        this.state = {
            columnFilters: props.columnFilters,
            distinctColumnValues: [],
            isDistinctColumnValuesLoading: false,
            showTab: true,
            selectedTab: Enums_1.ColumnMenuTab.Filter,
            editedColumnFilter: existingColumnFilter,
            currentTab: FilterFormComponent.getCurrentTab(existingColumnFilter),
            suppressClientSideFilter: false,
        };
    }
    componentWillUnmount() {
        this._isMounted = false;
    }
    componentDidMount() {
        if (this.props.currentColumn.dataType != 'Boolean') {
            this.loadPermittedValues();
        }
    }
    async loadPermittedValues(filter = '') {
        const { values: distinctColumnValues, suppressClientSideFilter } = await (0, runIfNotResolvedIn_1.runIfNotResolvedIn)(this.props.api.gridApi.internalApi.getDistinctFilterDisplayValuesForColumnForFiltersUI(this.props.currentColumn.columnId, filter, this.props.api.optionsApi.getColumnFilterOptions().valuesFilterOptions
            .showCurrentlyFilteredValuesOnly), () => this._isMounted && this.setState({ isDistinctColumnValuesLoading: true }));
        if (this._isMounted) {
            this.setState({
                distinctColumnValues,
                isDistinctColumnValuesLoading: false,
                suppressClientSideFilter,
            });
        }
    }
    render() {
        var _a, _b;
        let isFilterable = this.isFilterable();
        const columnFilterOptions = this.props.api.optionsApi.getColumnFilterOptions();
        const predicateDefs = this.props.api.columnFilterApi
            .getFilterPredicateDefsForColumn(this.props.currentColumn)
            .filter((predicate) => predicate.id !== 'BooleanToggle');
        let uiSelectedColumnValues = ((_b = (_a = this.state.editedColumnFilter) === null || _a === void 0 ? void 0 : _a.Predicate) === null || _b === void 0 ? void 0 : _b.PredicateId) === 'Values'
            ? this.state.editedColumnFilter.Predicate.Inputs
            : [];
        let isEmptyFilter = Helper_1.default.objectNotExists(this.state.editedColumnFilter) ||
            Helper_1.default.objectNotExists(this.state.editedColumnFilter.Predicate) ||
            Helper_1.default.objectNotExists(this.state.editedColumnFilter.Predicate.PredicateId);
        let closeButton = (React.createElement(ButtonClose_1.ButtonClose, { onClick: () => this.onCloseForm(), tooltip: null, accessLevel: 'Full' }));
        let clearFilterButton = (React.createElement(ButtonClear_1.ButtonClear, { onClick: () => this.onClearFilter(), disabled: isEmptyFilter, tooltip: null, accessLevel: 'Full', showText: true, showIcon: false }));
        const useAgGridStyle = !!columnFilterOptions.filterFormOptions.useAgGridFilterFormStyle;
        return (React.createElement("div", { className: "ab-FilterForm", "data-name": "filter-form" }, StringExtensions_1.StringExtensions.IsNullOrEmpty(isFilterable) ? (React.createElement(FilterFormPanel_1.FilterFormPanel, { style: panelStyle, ColumnMenuTab: this.state.selectedTab, ColumnMenuTabChanged: (e) => this.onSelectTab(e), IsAlwaysFilter: this.props.embedColumnMenu, clearFilterButton: clearFilterButton, closeButton: closeButton, showCloseButton: this.props.showCloseButton, autoApplyFilter: columnFilterOptions.autoApplyFilter ? true : false, useAgGridStyle: useAgGridStyle, applyFilterButtonDisabled: isEmptyFilter, onColumnFilterApplied: () => this.onColumnFilterApplied() }, this.state.selectedTab == Enums_1.ColumnMenuTab.Menu ? (React.createElement(ListBoxMenu_1.ListBoxMenu, { MenuItems: this.props.api.gridApi.internalApi.buildStandaloneColumnHeader(this.props.currentColumn), onMenuItemClick: (menuItem) => this.onMenuItemClick(menuItem) })) : (React.createElement(React.Fragment, null,
            this.state.showTab && (React.createElement(React.Fragment, null,
                React.createElement(Radio_1.default, { "data-name": "values", flex: 1, marginLeft: 1, checked: this.state.currentTab == 'values', onChange: () => this.setState({ currentTab: 'values' }) },
                    React.createElement(rebass_1.Flex, { fontSize: 'var( --ab-font-size-2)' }, "Column Values")),
                React.createElement(Radio_1.default, { "data-name": "predicates", marginLeft: 2, flex: 1, checked: this.state.currentTab == 'predicates', onChange: () => this.setState({ currentTab: 'predicates' }) },
                    React.createElement(rebass_1.Flex, { fontSize: 'var( --ab-font-size-2)' }, "Filters")))),
            this.state.currentTab === 'values' && (React.createElement(ListBoxFilterForm_1.ListBoxFilterForm, { disabled: this.isFilterDisabled(), suppressClientSideFilter: this.state.suppressClientSideFilter, isLoading: this.state.isDistinctColumnValuesLoading, onFilterChange: this.handleFilterChange, currentColumn: this.props.currentColumn, columns: this.props.columns, columnDistinctValues: this.state.distinctColumnValues, dataType: this.props.currentColumn.dataType, uiSelectedColumnValues: uiSelectedColumnValues, useAgGridStyle: useAgGridStyle, onColumnValueSelectedChange: (list) => this.onColumnValuesChange(list) })),
            this.state.currentTab === 'predicates' && (React.createElement(React.Fragment, null,
                ' ',
                this.state.showTab && React.createElement("hr", null),
                predicateDefs
                    .filter((p) => p.id !== 'Values' && p.id !== 'ExcludeValues')
                    .map((predicateDef, index) => this.renderColumnPredicate(predicateDef, index)))))))) : (React.createElement(HelpBlock_1.default, null, isFilterable))));
    }
    renderColumnPredicate(predicateDef, index) {
        var _a;
        const { editedColumnFilter } = this.state;
        const checked = ((_a = editedColumnFilter === null || editedColumnFilter === void 0 ? void 0 : editedColumnFilter.Predicate) === null || _a === void 0 ? void 0 : _a.PredicateId) === predicateDef.id;
        return (React.createElement(rebass_1.Flex, { className: "ab-FilterForm__predicate", key: index, flexDirection: "column" },
            React.createElement(Radio_1.default, { "data-name": predicateDef.id, disabled: this.isFilterDisabled(), fontSize: 'var(--ab-font-size-2)', margin: 1, flex: 1, checked: checked, onChange: () => this.selectColumnPredicate(predicateDef) }, predicateDef.label),
            React.createElement(rebass_1.Flex, { className: "ab-FilterForm__predicate_inputs", flexDirection: "column", flex: 0, marginLeft: 3, marginRight: 2 }, checked && this.renderPredicateInput(predicateDef, editedColumnFilter))));
    }
    renderPredicateInput(predicateDef, filter) {
        var _a;
        if ((predicateDef === null || predicateDef === void 0 ? void 0 : predicateDef.id) === 'BooleanToggle') {
            // custom tri-state checkbox: true, false, all(indeterminate)
            return (React.createElement(rebass_1.Flex, { className: "ab-FilterForm__predicate-input", flexDirection: "row", flex: 1, justifyContent: "center", alignItems: "center" },
                React.createElement(CheckBox_1.CheckBox, { disabled: this.isFilterDisabled(), checked: filter.Predicate.Inputs[0] === 'true'
                        ? true
                        : filter.Predicate.Inputs[0] === 'false'
                            ? false
                            : // 'all'
                                null, onChange: (checked) => {
                        // sequence: true -> false -> all -> true
                        const newCheckedValue = filter.Predicate.Inputs[0] === 'false' && checked === true
                            ? 'all'
                            : checked === true
                                ? 'true'
                                : 'false';
                        this.changeColumnPredicateInput(newCheckedValue, 0);
                    } })));
        }
        return (_a = predicateDef.inputs) === null || _a === void 0 ? void 0 : _a.map((predicateInput, index) => {
            var _a, _b;
            const showDatePicker = (_b = (_a = this.props.api.optionsApi) === null || _a === void 0 ? void 0 : _a.getColumnFilterOptions()) === null || _b === void 0 ? void 0 : _b.showDatePicker;
            if (predicateInput.type === 'date' && !showDatePicker) {
                return (React.createElement(AdaptableDateInlineInput_1.AdaptableDateInlineInput, { value: filter.Predicate.Inputs[index], onChange: (value) => this.changeColumnPredicateInput(value, index) }));
            }
            return (React.createElement(rebass_1.Flex, { key: index, flexDirection: "row" },
                React.createElement(AdaptableInput_1.default, { onMouseDown: (event) => {
                        if (predicateInput.type === 'date') {
                            // This prevents the ag-grid dropdown closing when a date is selected
                            event.stopPropagation();
                        }
                    }, disabled: this.isFilterDisabled(), type: predicateInput.type, autoFocus: index === 0, value: filter.Predicate.Inputs[index], onChange: (e) => this.changeColumnPredicateInput(e.target.value, index), mb: 1, flex: 1, fontSize: 2 })));
        });
    }
    isFilterDisabled() {
        var _a;
        return Boolean((_a = this.state.editedColumnFilter) === null || _a === void 0 ? void 0 : _a.IsSuspended);
    }
    isFilterable() {
        if (!this.props.currentColumn.filterable) {
            return 'Column is not filterable';
        }
        return '';
    }
    onSelectTab(tab) {
        this.setState({ selectedTab: tab });
    }
    onColumnValuesChange(columnValues) {
        const { editedColumnFilter } = this.state;
        editedColumnFilter.Predicate = {
            PredicateId: 'Values',
            Inputs: columnValues,
        };
        this.setState({ editedColumnFilter });
        this.persistFilter();
    }
    persistFilter() {
        const { editedColumnFilter } = this.state;
        //delete if empty
        if (editedColumnFilter.Predicate === undefined ||
            (editedColumnFilter.Predicate.PredicateId === 'Values' &&
                editedColumnFilter.Predicate.Inputs.length === 0)) {
            this.props.api.columnFilterApi.clearColumnFilterForColumn(editedColumnFilter.ColumnId);
            this.onCloseForm();
        }
        else {
            if (this.props.api.optionsApi.getColumnFilterOptions().autoApplyFilter) {
                this.props.onSetColumnFilter(editedColumnFilter);
            }
        }
    }
    onClearFilter() {
        const { editedColumnFilter } = this.state;
        editedColumnFilter.Predicate = undefined;
        this.setState({ editedColumnFilter });
        this.persistFilter();
    }
    onColumnFilterApplied() {
        // do some existing or real
        this.props.onAddColumnFilter(this.state.editedColumnFilter);
        this.props.onHideFilterForm();
    }
    onCloseForm() {
        this.props.onHideFilterForm();
    }
    onMenuItemClick(menuItem) {
        //action: Redux.Action
        if (menuItem.reduxAction) {
            this.props.onMenuItemClick(menuItem.reduxAction);
        }
        if (menuItem.onClick) {
            menuItem.onClick();
        }
        this.props.onHideFilterForm();
    }
    selectColumnPredicate(predicateDef) {
        var _a;
        const { editedColumnFilter } = this.state;
        editedColumnFilter.Predicate = {
            PredicateId: predicateDef.id,
            Inputs: ((_a = predicateDef.inputs) !== null && _a !== void 0 ? _a : []).map((i) => { var _a; return (_a = i.defaultValue) !== null && _a !== void 0 ? _a : ''; }),
        };
        this.setState({ editedColumnFilter });
        this.persistFilter();
    }
    changeColumnPredicateInput(value, index) {
        const { editedColumnFilter } = this.state;
        const newEditedColumnFilter = (0, Helper_1.cloneObject)(editedColumnFilter);
        newEditedColumnFilter.Predicate.Inputs[index] = value;
        this.setState({ editedColumnFilter: newEditedColumnFilter });
        if (this.props.api.optionsApi.getColumnFilterOptions().autoApplyFilter) {
            this.props.onSetColumnFilter(newEditedColumnFilter);
        }
    }
}
function mapStateToProps(state, ownProps) {
    return {
        currentColumn: ownProps.currentColumn,
        columns: state.Grid.Columns,
        columnFilters: (0, LayoutRedux_1.getColumnFilterSelector)(state),
        showCloseButton: ownProps.showCloseButton,
    };
}
function mapDispatchToProps(dispatch) {
    return {
        onMenuItemClick: (action) => dispatch(action),
        onClearColumnFilter: (columnFilter) => dispatch(LayoutRedux.LayoutColumnFilterClear(columnFilter)),
        onAddColumnFilter: (columnFilter) => dispatch(LayoutRedux.LayoutColumnFilterAdd(columnFilter)),
        onEditColumnFilter: (columnFilter) => dispatch(LayoutRedux.LayoutColumnFilterEdit(columnFilter)),
        onSetColumnFilter: (columnFilter) => dispatch(LayoutRedux.LayoutColumnFilterSet(columnFilter)),
        onHideFilterForm: () => dispatch(SystemRedux.SystemFilterFormHide()),
    };
}
const FilterForm = (0, react_redux_1.connect)(mapStateToProps, mapDispatchToProps)(FilterFormComponent);
const FilterFormReact = (columnFilterProps) => (0, renderWithAdaptableContext_1.renderWithAdaptableContext)(React.createElement(FilterForm, { api: columnFilterProps.Adaptable.api, currentColumn: columnFilterProps.Column, teamSharingActivated: false, embedColumnMenu: columnFilterProps.Adaptable.embedColumnMenu, showCloseButton: columnFilterProps.ShowCloseButton }), columnFilterProps.Adaptable);
exports.FilterFormReact = FilterFormReact;
