/**
 * DevExtreme (cjs/__internal/grids/grid_core/filter/m_filter_sync.js)
 * Version: 23.2.6 (build 24140-0112)
 * Build date: Sun May 19 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.filterSyncModule = exports.FilterSyncController = void 0;
var _deferred = require("../../../../core/utils/deferred");
var _type = require("../../../../core/utils/type");
var _filtering = _interopRequireDefault(require("../../../../ui/shared/filtering"));
var _ui = _interopRequireDefault(require("../../../../ui/widget/ui.errors"));
var _m_utils = require("../../../filter_builder/m_utils");
var _m_modules = _interopRequireDefault(require("../m_modules"));
var _m_utils2 = _interopRequireDefault(require("../m_utils"));
var _m_filter_custom_operations = require("./m_filter_custom_operations");

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    }
}

function _inheritsLoose(subClass, superClass) {
    subClass.prototype = Object.create(superClass.prototype);
    subClass.prototype.constructor = subClass;
    _setPrototypeOf(subClass, superClass)
}

function _setPrototypeOf(o, p) {
    _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function(o, p) {
        o.__proto__ = p;
        return o
    };
    return _setPrototypeOf(o, p)
}
const FILTER_ROW_OPERATIONS = ["=", "<>", "<", "<=", ">", ">=", "notcontains", "contains", "startswith", "endswith", "between"];
const FILTER_TYPES_INCLUDE = "include";
const FILTER_TYPES_EXCLUDE = "exclude";

function getColumnIdentifier(column) {
    return column.name || column.dataField
}

function checkForErrors(columns) {
    columns.forEach(column => {
        const identifier = getColumnIdentifier(column);
        if (!(0, _type.isDefined)(identifier) && column.allowFiltering) {
            throw new _ui.default.Error("E1049", column.caption)
        }
    })
}
const getEmptyFilterValues = function() {
    return {
        filterType: "include",
        filterValues: void 0
    }
};
const canSyncHeaderFilterWithFilterRow = function(column) {
    const filterValues = column.filterValues || [];
    return !_filtering.default.getGroupInterval(column) && !(column.headerFilter && column.headerFilter.dataSource) || 1 === filterValues.length && null === filterValues[0]
};
const getHeaderFilterFromCondition = function(headerFilterCondition, column) {
    if (!headerFilterCondition) {
        return {
            filterType: "include",
            filterValues: void 0
        }
    }
    let filterType;
    const selectedFilterOperation = headerFilterCondition[1];
    const value = headerFilterCondition[2];
    const hasArrayValue = Array.isArray(value);
    if (!hasArrayValue) {
        if (!canSyncHeaderFilterWithFilterRow(column)) {
            return {
                filterType: "include",
                filterValues: void 0
            }
        }
    }
    switch (selectedFilterOperation) {
        case "anyof":
        case "=":
            filterType = "include";
            break;
        case "noneof":
        case "<>":
            filterType = "exclude";
            break;
        default:
            return {
                filterType: "include", filterValues: void 0
            }
    }
    return {
        filterType: filterType,
        filterValues: hasArrayValue ? value : [value]
    }
};
const getConditionFromFilterRow = function(column) {
    const value = column.filterValue;
    if ((0, _type.isDefined)(value)) {
        const operation = column.selectedFilterOperation || column.defaultFilterOperation || (0, _m_utils.getDefaultOperation)(column);
        const filter = [getColumnIdentifier(column), operation, column.filterValue];
        return filter
    }
    return null
};
const getConditionFromHeaderFilter = function(column) {
    let selectedOperation;
    let value;
    const {
        filterValues: filterValues
    } = column;
    if (!filterValues) {
        return null
    }
    if (1 === filterValues.length && canSyncHeaderFilterWithFilterRow(column) && !Array.isArray(filterValues[0])) {
        "exclude" === column.filterType ? selectedOperation = "<>" : selectedOperation = "=";
        value = filterValues[0]
    } else {
        "exclude" === column.filterType ? selectedOperation = "noneof" : selectedOperation = "anyof";
        value = filterValues
    }
    return [getColumnIdentifier(column), selectedOperation, value]
};
const updateHeaderFilterCondition = function(columnsController, column, headerFilterCondition) {
    const headerFilter = getHeaderFilterFromCondition(headerFilterCondition, column);
    columnsController.columnOption(getColumnIdentifier(column), headerFilter)
};
const updateFilterRowCondition = function(columnsController, column, condition) {
    let filterRowOptions;
    let selectedFilterOperation = null === condition || void 0 === condition ? void 0 : condition[1];
    const filterValue = null === condition || void 0 === condition ? void 0 : condition[2];
    const filterOperations = column.filterOperations || column.defaultFilterOperations;
    if ((!filterOperations || filterOperations.indexOf(selectedFilterOperation) >= 0 || selectedFilterOperation === column.defaultFilterOperation) && FILTER_ROW_OPERATIONS.includes(selectedFilterOperation) && null !== filterValue) {
        if (selectedFilterOperation === column.defaultFilterOperation && !(0, _type.isDefined)(column.selectedFilterOperation)) {
            selectedFilterOperation = column.selectedFilterOperation
        }
        filterRowOptions = {
            filterValue: filterValue,
            selectedFilterOperation: selectedFilterOperation
        }
    } else {
        filterRowOptions = {
            filterValue: void 0,
            selectedFilterOperation: void 0
        }
    }
    columnsController.columnOption(getColumnIdentifier(column), filterRowOptions)
};
let FilterSyncController = function(_modules$Controller) {
    _inheritsLoose(FilterSyncController, _modules$Controller);

    function FilterSyncController() {
        return _modules$Controller.apply(this, arguments) || this
    }
    var _proto = FilterSyncController.prototype;
    _proto.init = function() {
        this._dataController = this.getController("data");
        this._columnsController = this.getController("columns");
        if (this._dataController.isFilterSyncActive()) {
            if (this._columnsController.isAllDataTypesDefined()) {
                this._initSync()
            } else {
                this._dataController.dataSourceChanged.add(() => this._initSync())
            }
        }
    };
    _proto.publicMethods = function() {
        return ["getCustomFilterOperations"]
    };
    _proto.syncFilterValue = function() {
        const that = this;
        const columns = this._columnsController.getFilteringColumns();
        this._skipSyncColumnOptions = true;
        columns.forEach(column => {
            const filterConditions = (0, _m_utils.getMatchedConditions)(that.option("filterValue"), getColumnIdentifier(column));
            if (1 === filterConditions.length) {
                const filterCondition = filterConditions[0];
                updateHeaderFilterCondition(this._columnsController, column, filterCondition);
                updateFilterRowCondition(this._columnsController, column, filterCondition)
            } else {
                (0, _type.isDefined)(column.filterValues) && updateHeaderFilterCondition(this._columnsController, column, null);
                (0, _type.isDefined)(column.filterValue) && updateFilterRowCondition(this._columnsController, column, null)
            }
        });
        this._skipSyncColumnOptions = false
    };
    _proto._initSync = function() {
        const columns = this._columnsController.getColumns();
        const pageIndex = this._dataController.pageIndex();
        checkForErrors(columns);
        if (!this.option("filterValue")) {
            const filteringColumns = this._columnsController.getFilteringColumns();
            const filterValue = this.getFilterValueFromColumns(filteringColumns);
            this._silentOption("filterValue", filterValue)
        }
        this.syncFilterValue();
        this._dataController.pageIndex(pageIndex)
    };
    _proto._getSyncFilterRow = function(filterValue, column) {
        const filter = getConditionFromFilterRow(column);
        if ((0, _type.isDefined)(filter)) {
            return (0, _m_utils.syncFilters)(filterValue, filter)
        }
        return (0, _m_utils.removeFieldConditionsFromFilter)(filterValue, getColumnIdentifier(column))
    };
    _proto._getSyncHeaderFilter = function(filterValue, column) {
        const filter = getConditionFromHeaderFilter(column);
        if (filter) {
            return (0, _m_utils.syncFilters)(filterValue, filter)
        }
        return (0, _m_utils.removeFieldConditionsFromFilter)(filterValue, getColumnIdentifier(column))
    };
    _proto.getFilterValueFromColumns = function(columns) {
        if (!this._dataController.isFilterSyncActive()) {
            return null
        }
        const filterValue = ["and"];
        columns && columns.forEach(column => {
            const headerFilter = getConditionFromHeaderFilter(column);
            const filterRow = getConditionFromFilterRow(column);
            headerFilter && (0, _m_utils.addItem)(headerFilter, filterValue);
            filterRow && (0, _m_utils.addItem)(filterRow, filterValue)
        });
        return (0, _m_utils.getNormalizedFilter)(filterValue)
    };
    _proto.syncFilterRow = function(column, filterValue) {
        this.option("filterValue", this._getSyncFilterRow(this.option("filterValue"), column))
    };
    _proto.syncHeaderFilter = function(column) {
        this.option("filterValue", this._getSyncHeaderFilter(this.option("filterValue"), column))
    };
    _proto.getCustomFilterOperations = function() {
        var _a;
        const filterBuilderCustomOperations = null !== (_a = this.option("filterBuilder.customOperations")) && void 0 !== _a ? _a : [];
        return [(0, _m_filter_custom_operations.anyOf)(this.component), (0, _m_filter_custom_operations.noneOf)(this.component)].concat(filterBuilderCustomOperations)
    };
    return FilterSyncController
}(_m_modules.default.Controller);
exports.FilterSyncController = FilterSyncController;
const data = Base => function(_Base) {
    _inheritsLoose(DataControllerFilterSyncExtender, _Base);

    function DataControllerFilterSyncExtender() {
        return _Base.apply(this, arguments) || this
    }
    var _proto2 = DataControllerFilterSyncExtender.prototype;
    _proto2.optionChanged = function(args) {
        switch (args.name) {
            case "filterValue":
                this._applyFilter();
                this.isFilterSyncActive() && this._filterSyncController.syncFilterValue();
                args.handled = true;
                break;
            case "filterSyncEnabled":
                args.handled = true;
                break;
            case "columns":
                if (this.isFilterSyncActive()) {
                    const column = this._columnsController.getColumnByPath(args.fullName);
                    if (column && !this._filterSyncController._skipSyncColumnOptions) {
                        const propertyName = this._parseColumnPropertyName(args.fullName);
                        this._filterSyncController._skipSyncColumnOptions = true;
                        if ("filterType" === propertyName) {
                            if ("exclude" === args.value || "exclude" === args.previousValue) {
                                this._filterSyncController.syncHeaderFilter(column)
                            }
                        } else if ("filterValues" === propertyName) {
                            this._filterSyncController.syncHeaderFilter(column)
                        } else if (["filterValue", "selectedFilterOperation"].includes(propertyName)) {
                            this._filterSyncController.syncFilterRow(column, column.filterValue)
                        }
                        this._filterSyncController._skipSyncColumnOptions = false
                    }
                }
                _Base.prototype.optionChanged.call(this, args);
                break;
            default:
                _Base.prototype.optionChanged.call(this, args)
        }
    };
    _proto2.isFilterSyncActive = function() {
        const filterSyncEnabledValue = this.option("filterSyncEnabled");
        return "auto" === filterSyncEnabledValue ? this.option("filterPanel.visible") : filterSyncEnabledValue
    };
    _proto2.skipCalculateColumnFilters = function() {
        return ((0, _type.isDefined)(this.option("filterValue")) || this._filterSyncController._skipSyncColumnOptions) && this.isFilterSyncActive()
    };
    _proto2._calculateAdditionalFilter = function() {
        if (false === this.option("filterPanel.filterEnabled")) {
            return _Base.prototype._calculateAdditionalFilter.call(this)
        }
        const filters = [_Base.prototype._calculateAdditionalFilter.call(this)];
        const columns = this._columnsController.getFilteringColumns();
        let filterValue = this.option("filterValue");
        if (this.isFilterSyncActive()) {
            const currentColumnForHeaderFilter = this._headerFilterController.getCurrentColumn();
            const currentColumnForFilterRow = this._applyFilterController.getCurrentColumnForFiltering();
            const currentColumn = currentColumnForHeaderFilter || currentColumnForFilterRow;
            const needRemoveCurrentColumnFilter = currentColumnForHeaderFilter || (0, _type.isDefined)(null === currentColumnForFilterRow || void 0 === currentColumnForFilterRow ? void 0 : currentColumnForFilterRow.filterValue);
            if (needRemoveCurrentColumnFilter && filterValue) {
                filterValue = (0, _m_utils.removeFieldConditionsFromFilter)(filterValue, getColumnIdentifier(currentColumn))
            }
        }
        const customOperations = this._filterSyncController.getCustomFilterOperations();
        const calculatedFilterValue = (0, _m_utils.getFilterExpression)(filterValue, columns, customOperations, "filterBuilder");
        if (calculatedFilterValue) {
            filters.push(calculatedFilterValue)
        }
        return _m_utils2.default.combineFilters(filters)
    };
    _proto2._parseColumnPropertyName = function(fullName) {
        const matched = fullName.match(/.*\.(.*)/);
        if (matched) {
            return matched[1]
        }
        return null
    };
    _proto2.clearFilter = function(filterName) {
        this.component.beginUpdate();
        if (arguments.length > 0) {
            if ("filterValue" === filterName) {
                this.option("filterValue", null)
            }
            _Base.prototype.clearFilter.call(this, filterName)
        } else {
            this.option("filterValue", null);
            _Base.prototype.clearFilter.call(this)
        }
        this.component.endUpdate()
    };
    _proto2._applyFilter = function() {
        if (this._filterSyncController._skipSyncColumnOptions) {
            return (new _deferred.Deferred).resolve()
        }
        return _Base.prototype._applyFilter.apply(this, arguments)
    };
    return DataControllerFilterSyncExtender
}(Base);
const columnHeadersView = Base => function(_Base2) {
    _inheritsLoose(ColumnHeadersViewFilterSyncExtender, _Base2);

    function ColumnHeadersViewFilterSyncExtender() {
        return _Base2.apply(this, arguments) || this
    }
    var _proto3 = ColumnHeadersViewFilterSyncExtender.prototype;
    _proto3.optionChanged = function(args) {
        if ("filterValue" === args.name) {
            this._updateHeaderFilterIndicators()
        } else {
            _Base2.prototype.optionChanged.call(this, args)
        }
    };
    _proto3._isHeaderFilterEmpty = function(column) {
        if (this._dataController.isFilterSyncActive()) {
            return !(0, _m_utils.filterHasField)(this.option("filterValue"), getColumnIdentifier(column))
        }
        return _Base2.prototype._isHeaderFilterEmpty.call(this, column)
    };
    _proto3._needUpdateFilterIndicators = function() {
        return !this._dataController.isFilterSyncActive()
    };
    return ColumnHeadersViewFilterSyncExtender
}(Base);
const filterSyncModule = {
    defaultOptions: () => ({
        filterValue: null,
        filterSyncEnabled: "auto"
    }),
    controllers: {
        filterSync: FilterSyncController
    },
    extenders: {
        controllers: {
            data: data
        },
        views: {
            columnHeadersView: columnHeadersView
        }
    }
};
exports.filterSyncModule = filterSyncModule;
