/**
 * DevExtreme (esm/__internal/grids/grid_core/columns_controller/m_columns_controller.js)
 * Version: 22.2.7 (build 23185-0311)
 * Build date: Tue Jul 04 2023
 *
 * Copyright (c) 2012 - 2023 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
import _extends from "@babel/runtime/helpers/esm/extends";
import config from "../../../../core/config";
import $ from "../../../../core/renderer";
import Callbacks from "../../../../core/utils/callbacks";
import {
    compileGetter
} from "../../../../core/utils/data";
import {
    Deferred,
    when
} from "../../../../core/utils/deferred";
import {
    extend
} from "../../../../core/utils/extend";
import {
    captionize
} from "../../../../core/utils/inflector";
import {
    each,
    map
} from "../../../../core/utils/iterator";
import {
    orderEach
} from "../../../../core/utils/object";
import {
    isDefined,
    isFunction,
    isNumeric,
    isObject,
    isPlainObject,
    isString
} from "../../../../core/utils/type";
import variableWrapper from "../../../../core/utils/variable_wrapper";
import Store from "../../../../data/abstract_store";
import {
    DataSource
} from "../../../../data/data_source/data_source";
import {
    normalizeDataSourceOptions
} from "../../../../data/data_source/utils";
import dateLocalization from "../../../../localization/date";
import messageLocalization from "../../../../localization/message";
import filterUtils from "../../../../ui/shared/filtering";
import errors from "../../../../ui/widget/ui.errors";
import modules from "../m_modules";
import gridCoreUtils from "../m_utils";
import {
    COLUMN_CHOOSER_LOCATION,
    COLUMN_OPTION_REGEXP,
    COMMAND_EXPAND_CLASS,
    DATATYPE_OPERATIONS,
    DETAIL_COMMAND_COLUMN_NAME,
    GROUP_COMMAND_COLUMN_NAME,
    GROUP_LOCATION,
    MAX_SAFE_INTEGER,
    USER_STATE_FIELD_NAMES
} from "./const";
import {
    addExpandColumn,
    applyUserState,
    assignColumns,
    columnOptionCore,
    convertOwnerBandToColumnReference,
    createColumn,
    createColumnsFromDataSource,
    createColumnsFromOptions,
    defaultSetCellValue,
    digitsCount,
    findColumn,
    fireColumnsChanged,
    getAlignmentByDataType,
    getChildrenByBandColumn,
    getColumnByIndexes,
    getColumnIndexByVisibleIndex,
    getCustomizeTextByDataType,
    getDataColumns,
    getFixedPosition,
    getParentBandColumns,
    getRowCount,
    getSerializationFormat,
    getValueDataType,
    isColumnFixed,
    isCustomCommandColumn,
    isSortOrderValid,
    mergeColumns,
    moveColumnToGroup,
    numberToString,
    processBandColumns,
    processExpandColumns,
    resetBandColumnsCache,
    resetColumnsCache,
    setFilterOperationsAsDefaultValues,
    sortColumns,
    strictParseNumber,
    updateColumnChanges,
    updateColumnGroupIndexes,
    updateIndexes,
    updateSerializers
} from "./m_columns_controller_utils";
export class ColumnsController extends modules.Controller {
    _getExpandColumnOptions() {
        return {
            type: "expand",
            command: "expand",
            width: "auto",
            cssClass: COMMAND_EXPAND_CLASS,
            allowEditing: false,
            allowGrouping: false,
            allowSorting: false,
            allowResizing: false,
            allowReordering: false,
            allowHiding: false
        }
    }
    _getFirstItems(dataSource) {
        var groupsCount;
        var items = [];
        if (dataSource && dataSource.items().length > 0) {
            groupsCount = gridCoreUtils.normalizeSortingInfo(dataSource.group()).length;
            items = function getFirstItemsCore(items, groupsCount) {
                if (!items || !groupsCount) {
                    return items
                }
                for (var i = 0; i < items.length; i++) {
                    var childItems = getFirstItemsCore(items[i].items || items[i].collapsedItems, groupsCount - 1);
                    if (childItems && childItems.length) {
                        return childItems
                    }
                }
            }(dataSource.items(), groupsCount) || []
        }
        return items
    }
    _endUpdateCore() {
        !this._skipProcessingColumnsChange && fireColumnsChanged(this)
    }
    init(isApplyingUserState) {
        var columns = this.option("columns");
        this._commandColumns = this._commandColumns || [];
        this._columns = this._columns || [];
        this._isColumnsFromOptions = !!columns;
        if (this._isColumnsFromOptions) {
            assignColumns(this, columns ? createColumnsFromOptions(this, columns) : []);
            applyUserState(this)
        } else {
            assignColumns(this, this._columnsUserState ? createColumnsFromOptions(this, this._columnsUserState) : this._columns)
        }
        addExpandColumn(this);
        if (this._dataSourceApplied) {
            this.applyDataSource(this._dataSource, true, isApplyingUserState)
        } else {
            updateIndexes(this)
        }
        this._checkColumns()
    }
    callbackNames() {
        return ["columnsChanged"]
    }
    getColumnByPath(path, columns) {
        var column;
        var columnIndexes = [];
        path.replace(COLUMN_OPTION_REGEXP, (_, columnIndex) => {
            columnIndexes.push(parseInt(columnIndex));
            return ""
        });
        if (columnIndexes.length) {
            if (columns) {
                column = columnIndexes.reduce((column, index) => column && column.columns && column.columns[index], {
                    columns: columns
                })
            } else {
                column = getColumnByIndexes(this, columnIndexes)
            }
        }
        return column
    }
    optionChanged(args) {
        var needUpdateRequireResize;
        switch (args.name) {
            case "adaptColumnWidthByRatio":
                args.handled = true;
                break;
            case "dataSource":
                if (args.value !== args.previousValue && !this.option("columns") && (!Array.isArray(args.value) || !Array.isArray(args.previousValue))) {
                    this._columns = []
                }
                break;
            case "columns":
                needUpdateRequireResize = this._skipProcessingColumnsChange;
                args.handled = true;
                if (!this._skipProcessingColumnsChange) {
                    if (args.name === args.fullName) {
                        this._columnsUserState = null;
                        this._ignoreColumnOptionNames = null;
                        this.init()
                    } else {
                        this._columnOptionChanged(args);
                        needUpdateRequireResize = true
                    }
                }
                if (needUpdateRequireResize) {
                    this._updateRequireResize(args)
                }
                break;
            case "commonColumnSettings":
            case "columnAutoWidth":
            case "allowColumnResizing":
            case "allowColumnReordering":
            case "columnFixing":
            case "grouping":
            case "groupPanel":
            case "regenerateColumnsByVisibleItems":
            case "customizeColumns":
            case "columnHidingEnabled":
            case "dateSerializationFormat":
            case "columnResizingMode":
            case "columnMinWidth":
            case "columnWidth":
                args.handled = true;
                var ignoreColumnOptionNames = "columnWidth" === args.fullName && ["width"];
                this.reinit(ignoreColumnOptionNames);
                break;
            case "rtlEnabled":
                this.reinit();
                break;
            default:
                super.optionChanged(args)
        }
    }
    _columnOptionChanged(args) {
        var columnOptionValue = {};
        var column = this.getColumnByPath(args.fullName);
        var columnOptionName = args.fullName.replace(COLUMN_OPTION_REGEXP, "");
        if (column) {
            if (columnOptionName) {
                columnOptionValue[columnOptionName] = args.value
            } else {
                columnOptionValue = args.value
            }
            this._skipProcessingColumnsChange = args.fullName;
            this.columnOption(column.index, columnOptionValue);
            this._skipProcessingColumnsChange = false
        }
    }
    _updateRequireResize(args) {
        var {
            component: component
        } = this;
        if ("width" === args.fullName.replace(COLUMN_OPTION_REGEXP, "") && component._updateLockCount) {
            component._requireResize = true
        }
    }
    publicMethods() {
        return ["addColumn", "deleteColumn", "columnOption", "columnCount", "clearSorting", "clearGrouping", "getVisibleColumns", "getVisibleColumnIndex"]
    }
    applyDataSource(dataSource, forceApplying, isApplyingUserState) {
        var isDataSourceLoaded = dataSource && dataSource.isLoaded();
        this._dataSource = dataSource;
        if (!this._dataSourceApplied || 0 === this._dataSourceColumnsCount || forceApplying || this.option("regenerateColumnsByVisibleItems")) {
            if (isDataSourceLoaded) {
                if (!this._isColumnsFromOptions) {
                    var columnsFromDataSource = createColumnsFromDataSource(this, dataSource);
                    if (columnsFromDataSource.length) {
                        assignColumns(this, columnsFromDataSource);
                        this._dataSourceColumnsCount = this._columns.length;
                        applyUserState(this)
                    }
                }
                return this.updateColumns(dataSource, forceApplying, isApplyingUserState)
            }
            this._dataSourceApplied = false;
            updateIndexes(this)
        } else if (isDataSourceLoaded && !this.isAllDataTypesDefined(true) && this.updateColumnDataTypes(dataSource)) {
            updateColumnChanges(this, "columns");
            fireColumnsChanged(this);
            return (new Deferred).reject().promise()
        }
    }
    reset() {
        this._dataSource = null;
        this._dataSourceApplied = false;
        this._dataSourceColumnsCount = void 0;
        this.reinit()
    }
    resetColumnsCache() {
        this._visibleColumns = void 0;
        this._fixedColumns = void 0;
        this._rowCount = void 0;
        resetBandColumnsCache(this)
    }
    reinit(ignoreColumnOptionNames) {
        this._columnsUserState = this.getUserState();
        this._ignoreColumnOptionNames = ignoreColumnOptionNames || null;
        this.init();
        if (ignoreColumnOptionNames) {
            this._ignoreColumnOptionNames = null
        }
    }
    isInitialized() {
        return !!this._columns.length || !!this.option("columns")
    }
    isDataSourceApplied() {
        return this._dataSourceApplied
    }
    getCommonSettings(column) {
        var _a, _b;
        var commonColumnSettings = (!column || !column.type) && this.option("commonColumnSettings") || {};
        var groupingOptions = null !== (_a = this.option("grouping")) && void 0 !== _a ? _a : {};
        var groupPanelOptions = null !== (_b = this.option("groupPanel")) && void 0 !== _b ? _b : {};
        return extend({
            allowFixing: this.option("columnFixing.enabled"),
            allowResizing: this.option("allowColumnResizing") || void 0,
            allowReordering: this.option("allowColumnReordering"),
            minWidth: this.option("columnMinWidth"),
            width: this.option("columnWidth"),
            autoExpandGroup: groupingOptions.autoExpandAll,
            allowCollapsing: groupingOptions.allowCollapsing,
            allowGrouping: groupPanelOptions.allowColumnDragging && groupPanelOptions.visible || groupingOptions.contextMenuEnabled
        }, commonColumnSettings)
    }
    isColumnOptionUsed(optionName) {
        for (var i = 0; i < this._columns.length; i++) {
            if (this._columns[i][optionName]) {
                return true
            }
        }
    }
    isAllDataTypesDefined(checkSerializers) {
        var columns = this._columns;
        if (!columns.length) {
            return false
        }
        for (var i = 0; i < columns.length; i++) {
            if (!columns[i].dataField && columns[i].calculateCellValue === columns[i].defaultCalculateCellValue) {
                continue
            }
            if (!columns[i].dataType || checkSerializers && columns[i].deserializeValue && void 0 === columns[i].serializationFormat) {
                return false
            }
        }
        return true
    }
    getColumns() {
        return this._columns
    }
    isBandColumnsUsed() {
        return this.getColumns().some(column => column.isBand)
    }
    getGroupColumns() {
        var result = [];
        each(this._columns, (function() {
            if (isDefined(this.groupIndex)) {
                result[this.groupIndex] = this
            }
        }));
        return result
    }
    _shouldReturnVisibleColumns() {
        return true
    }
    _compileVisibleColumns(rowIndex) {
        this._visibleColumns = this._visibleColumns || this._compileVisibleColumnsCore();
        rowIndex = isDefined(rowIndex) ? rowIndex : this._visibleColumns.length - 1;
        return this._visibleColumns[rowIndex] || []
    }
    getVisibleColumns(rowIndex, isBase) {
        if (!this._shouldReturnVisibleColumns()) {
            return []
        }
        return this._compileVisibleColumns.apply(this, arguments)
    }
    getFixedColumns(rowIndex) {
        this._fixedColumns = this._fixedColumns || this._getFixedColumnsCore();
        rowIndex = isDefined(rowIndex) ? rowIndex : this._fixedColumns.length - 1;
        return this._fixedColumns[rowIndex] || []
    }
    getFilteringColumns() {
        return this.getColumns().filter(item => (item.dataField || item.name) && (item.allowFiltering || item.allowHeaderFiltering)).map(item => {
            var field = extend(true, {}, item);
            if (!isDefined(field.dataField)) {
                field.dataField = field.name
            }
            field.filterOperations = item.filterOperations !== item.defaultFilterOperations ? field.filterOperations : null;
            return field
        })
    }
    getColumnIndexOffset() {
        return 0
    }
    _getFixedColumnsCore() {
        var result = [];
        var rowCount = this.getRowCount();
        var isColumnFixing = this._isColumnFixing();
        var transparentColumn = {
            command: "transparent"
        };
        var transparentColspan = 0;
        var notFixedColumnCount;
        var transparentColumnIndex;
        var lastFixedPosition;
        if (isColumnFixing) {
            for (var i = 0; i <= rowCount; i++) {
                notFixedColumnCount = 0;
                lastFixedPosition = null;
                transparentColumnIndex = null;
                var visibleColumns = this.getVisibleColumns(i, true);
                for (var j = 0; j < visibleColumns.length; j++) {
                    var prevColumn = visibleColumns[j - 1];
                    var column = visibleColumns[j];
                    if (!column.fixed) {
                        if (0 === i) {
                            if (column.isBand && column.colspan) {
                                transparentColspan += column.colspan
                            } else {
                                transparentColspan++
                            }
                        }
                        notFixedColumnCount++;
                        if (!isDefined(transparentColumnIndex)) {
                            transparentColumnIndex = j
                        }
                    } else if (prevColumn && prevColumn.fixed && getFixedPosition(this, prevColumn) !== getFixedPosition(this, column)) {
                        if (!isDefined(transparentColumnIndex)) {
                            transparentColumnIndex = j
                        }
                    } else {
                        lastFixedPosition = column.fixedPosition
                    }
                }
                if (0 === i && (0 === notFixedColumnCount || notFixedColumnCount >= visibleColumns.length)) {
                    return []
                }
                if (!isDefined(transparentColumnIndex)) {
                    transparentColumnIndex = "right" === lastFixedPosition ? 0 : visibleColumns.length
                }
                result[i] = visibleColumns.slice(0);
                if (!transparentColumn.colspan) {
                    transparentColumn.colspan = transparentColspan
                }
                result[i].splice(transparentColumnIndex, notFixedColumnCount, transparentColumn)
            }
        }
        return result.map(columns => columns.map(column => {
            var newColumn = _extends({}, column);
            if (newColumn.headerId) {
                newColumn.headerId += "-fixed"
            }
            return newColumn
        }))
    }
    _isColumnFixing() {
        var isColumnFixing = this.option("columnFixing.enabled");
        !isColumnFixing && each(this._columns, (_, column) => {
            if (column.fixed) {
                isColumnFixing = true;
                return false
            }
        });
        return isColumnFixing
    }
    _getExpandColumnsCore() {
        return this.getGroupColumns()
    }
    getExpandColumns() {
        var expandColumns = this._getExpandColumnsCore();
        var expandColumn;
        var firstGroupColumn = expandColumns.filter(column => 0 === column.groupIndex)[0];
        var isFixedFirstGroupColumn = firstGroupColumn && firstGroupColumn.fixed;
        var isColumnFixing = this._isColumnFixing();
        var rtlEnabled = this.option("rtlEnabled");
        if (expandColumns.length) {
            expandColumn = this.columnOption("command:expand")
        }
        expandColumns = map(expandColumns, column => extend({}, column, {
            visibleWidth: null,
            minWidth: null,
            cellTemplate: !isDefined(column.groupIndex) ? column.cellTemplate : null,
            headerCellTemplate: null,
            fixed: !isDefined(column.groupIndex) || !isFixedFirstGroupColumn ? isColumnFixing : true,
            fixedPosition: rtlEnabled ? "right" : "left"
        }, expandColumn, {
            index: column.index,
            type: column.type || GROUP_COMMAND_COLUMN_NAME
        }));
        return expandColumns
    }
    getBandColumnsCache() {
        if (!this._bandColumnsCache) {
            var columns = this._columns;
            var columnChildrenByIndex = {};
            var columnParentByIndex = {};
            var isPlain = true;
            columns.forEach(column => {
                var {
                    ownerBand: ownerBand
                } = column;
                var parentIndex = isObject(ownerBand) ? ownerBand.index : ownerBand;
                var parent = columns[parentIndex];
                if (column.hasColumns) {
                    isPlain = false
                }
                if (column.colspan) {
                    column.colspan = void 0
                }
                if (column.rowspan) {
                    column.rowspan = void 0
                }
                if (parent) {
                    columnParentByIndex[column.index] = parent
                } else {
                    parentIndex = -1
                }
                columnChildrenByIndex[parentIndex] = columnChildrenByIndex[parentIndex] || [];
                columnChildrenByIndex[parentIndex].push(column)
            });
            this._bandColumnsCache = {
                isPlain: isPlain,
                columnChildrenByIndex: columnChildrenByIndex,
                columnParentByIndex: columnParentByIndex
            }
        }
        return this._bandColumnsCache
    }
    _isColumnVisible(column) {
        return column.visible && this.isParentColumnVisible(column.index)
    }
    _isColumnInGroupPanel(column) {
        return isDefined(column.groupIndex) && !column.showWhenGrouped
    }
    hasVisibleDataColumns() {
        var columns = this._columns;
        return columns.some(column => {
            var isVisible = this._isColumnVisible(column);
            var isInGroupPanel = this._isColumnInGroupPanel(column);
            var isCommand = !!column.command;
            return isVisible && !isInGroupPanel && !isCommand
        })
    }
    _compileVisibleColumnsCore() {
        var bandColumnsCache = this.getBandColumnsCache();
        var columns = mergeColumns(this, this._columns, this._commandColumns, true);
        processBandColumns(this, columns, bandColumnsCache);
        var indexedColumns = this._getIndexedColumns(columns);
        var visibleColumns = this._getVisibleColumnsFromIndexed(indexedColumns);
        var isDataColumnsInvisible = !this.hasVisibleDataColumns();
        if (isDataColumnsInvisible && this._columns.length) {
            visibleColumns[visibleColumns.length - 1].push({
                command: "empty"
            })
        }
        return visibleColumns
    }
    _getIndexedColumns(columns) {
        var rtlEnabled = this.option("rtlEnabled");
        var rowCount = this.getRowCount();
        var columnDigitsCount = digitsCount(columns.length);
        var bandColumnsCache = this.getBandColumnsCache();
        var positiveIndexedColumns = [];
        var negativeIndexedColumns = [];
        for (var i = 0; i < rowCount; i += 1) {
            negativeIndexedColumns[i] = [{}];
            positiveIndexedColumns[i] = [{}, {}, {}]
        }
        columns.forEach(column => {
            var _a, _b, _c, _d;
            var {
                visibleIndex: visibleIndex
            } = column;
            var indexedColumns;
            var parentBandColumns = getParentBandColumns(column.index, bandColumnsCache.columnParentByIndex);
            var isVisible = this._isColumnVisible(column);
            var isInGroupPanel = this._isColumnInGroupPanel(column);
            if (isVisible && !isInGroupPanel) {
                var rowIndex = parentBandColumns.length;
                if (visibleIndex < 0) {
                    visibleIndex = -visibleIndex;
                    indexedColumns = negativeIndexedColumns[rowIndex]
                } else {
                    column.fixed = null !== (_b = null === (_a = parentBandColumns[0]) || void 0 === _a ? void 0 : _a.fixed) && void 0 !== _b ? _b : column.fixed;
                    column.fixedPosition = null !== (_d = null === (_c = parentBandColumns[0]) || void 0 === _c ? void 0 : _c.fixedPosition) && void 0 !== _d ? _d : column.fixedPosition;
                    if (column.fixed) {
                        var isDefaultCommandColumn = !!column.command && !isCustomCommandColumn(this, column);
                        var isFixedToEnd = "right" === column.fixedPosition;
                        if (rtlEnabled && !isDefaultCommandColumn) {
                            isFixedToEnd = !isFixedToEnd
                        }
                        indexedColumns = isFixedToEnd ? positiveIndexedColumns[rowIndex][2] : positiveIndexedColumns[rowIndex][0]
                    } else {
                        indexedColumns = positiveIndexedColumns[rowIndex][1]
                    }
                }
                if (parentBandColumns.length) {
                    visibleIndex = numberToString(visibleIndex, columnDigitsCount);
                    for (var _i = parentBandColumns.length - 1; _i >= 0; _i -= 1) {
                        visibleIndex = numberToString(parentBandColumns[_i].visibleIndex, columnDigitsCount) + visibleIndex
                    }
                }
                indexedColumns[visibleIndex] = indexedColumns[visibleIndex] || [];
                indexedColumns[visibleIndex].push(column)
            }
        });
        return {
            positiveIndexedColumns: positiveIndexedColumns,
            negativeIndexedColumns: negativeIndexedColumns
        }
    }
    _getVisibleColumnsFromIndexed(_ref) {
        var _this = this;
        var {
            positiveIndexedColumns: positiveIndexedColumns,
            negativeIndexedColumns: negativeIndexedColumns
        } = _ref;
        var result = [];
        var rowCount = this.getRowCount();
        var expandColumns = mergeColumns(this, this.getExpandColumns(), this._columns);
        var rowspanGroupColumns = 0;
        var rowspanExpandColumns = 0;
        var _loop = function(rowIndex) {
            result.push([]);
            orderEach(negativeIndexedColumns[rowIndex], (_, columns) => {
                result[rowIndex].unshift.apply(result[rowIndex], columns)
            });
            var firstPositiveIndexColumn = result[rowIndex].length;
            var positiveIndexedRowColumns = positiveIndexedColumns[rowIndex];
            positiveIndexedRowColumns.forEach(columnsByFixing => {
                orderEach(columnsByFixing, (_, columnsByVisibleIndex) => {
                    result[rowIndex].push.apply(result[rowIndex], columnsByVisibleIndex)
                })
            });
            if (rowspanExpandColumns <= rowIndex) {
                rowspanExpandColumns += processExpandColumns.call(_this, result[rowIndex], expandColumns, DETAIL_COMMAND_COLUMN_NAME, firstPositiveIndexColumn)
            }
            if (rowspanGroupColumns <= rowIndex) {
                rowspanGroupColumns += processExpandColumns.call(_this, result[rowIndex], expandColumns, GROUP_COMMAND_COLUMN_NAME, firstPositiveIndexColumn)
            }
        };
        for (var rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
            _loop(rowIndex)
        }
        result.push(getDataColumns(result));
        return result
    }
    getInvisibleColumns(columns, bandColumnIndex) {
        var that = this;
        var result = [];
        var hiddenColumnsByBand;
        columns = columns || that._columns;
        each(columns, (_, column) => {
            if (column.ownerBand !== bandColumnIndex) {
                return
            }
            if (column.isBand) {
                if (!column.visible) {
                    hiddenColumnsByBand = that.getChildrenByBandColumn(column.index)
                } else {
                    hiddenColumnsByBand = that.getInvisibleColumns(that.getChildrenByBandColumn(column.index), column.index)
                }
                if (hiddenColumnsByBand.length) {
                    result.push(column);
                    result = result.concat(hiddenColumnsByBand)
                }
                return
            }
            if (!column.visible) {
                result.push(column)
            }
        });
        return result
    }
    getChooserColumns(getAllColumns) {
        var columns = getAllColumns ? this.getColumns() : this.getInvisibleColumns();
        var columnChooserColumns = columns.filter(column => column.showInColumnChooser);
        var sortOrder = this.option("columnChooser.sortOrder");
        return sortColumns(columnChooserColumns, sortOrder)
    }
    allowMoveColumn(fromVisibleIndex, toVisibleIndex, sourceLocation, targetLocation) {
        var columnIndex = getColumnIndexByVisibleIndex(this, fromVisibleIndex, sourceLocation);
        var sourceColumn = this._columns[columnIndex];
        if (sourceColumn && (sourceColumn.allowReordering || sourceColumn.allowGrouping || sourceColumn.allowHiding)) {
            if (sourceLocation === targetLocation) {
                if (sourceLocation === COLUMN_CHOOSER_LOCATION) {
                    return false
                }
                fromVisibleIndex = isObject(fromVisibleIndex) ? fromVisibleIndex.columnIndex : fromVisibleIndex;
                toVisibleIndex = isObject(toVisibleIndex) ? toVisibleIndex.columnIndex : toVisibleIndex;
                return fromVisibleIndex !== toVisibleIndex && fromVisibleIndex + 1 !== toVisibleIndex
            }
            if (sourceLocation === GROUP_LOCATION && targetLocation !== COLUMN_CHOOSER_LOCATION || targetLocation === GROUP_LOCATION) {
                return sourceColumn && sourceColumn.allowGrouping
            }
            if (sourceLocation === COLUMN_CHOOSER_LOCATION || targetLocation === COLUMN_CHOOSER_LOCATION) {
                return sourceColumn && sourceColumn.allowHiding
            }
            return true
        }
        return false
    }
    moveColumn(fromVisibleIndex, toVisibleIndex, sourceLocation, targetLocation) {
        var options = {};
        var prevGroupIndex;
        var fromIndex = getColumnIndexByVisibleIndex(this, fromVisibleIndex, sourceLocation);
        var toIndex = getColumnIndexByVisibleIndex(this, toVisibleIndex, targetLocation);
        var targetGroupIndex;
        if (fromIndex >= 0) {
            var column = this._columns[fromIndex];
            toVisibleIndex = isObject(toVisibleIndex) ? toVisibleIndex.columnIndex : toVisibleIndex;
            targetGroupIndex = toIndex >= 0 ? this._columns[toIndex].groupIndex : -1;
            if (isDefined(column.groupIndex) && sourceLocation === GROUP_LOCATION) {
                if (targetGroupIndex > column.groupIndex) {
                    targetGroupIndex--
                }
                if (targetLocation !== GROUP_LOCATION) {
                    options.groupIndex = void 0
                } else {
                    prevGroupIndex = column.groupIndex;
                    delete column.groupIndex;
                    updateColumnGroupIndexes(this)
                }
            }
            if (targetLocation === GROUP_LOCATION) {
                options.groupIndex = moveColumnToGroup(this, column, targetGroupIndex);
                column.groupIndex = prevGroupIndex
            } else if (toVisibleIndex >= 0) {
                var targetColumn = this._columns[toIndex];
                if (!targetColumn || column.ownerBand !== targetColumn.ownerBand) {
                    options.visibleIndex = MAX_SAFE_INTEGER
                } else if (isColumnFixed(this, column) ^ isColumnFixed(this, targetColumn)) {
                    options.visibleIndex = MAX_SAFE_INTEGER
                } else {
                    options.visibleIndex = targetColumn.visibleIndex
                }
            }
            var isVisible = targetLocation !== COLUMN_CHOOSER_LOCATION;
            if (column.visible !== isVisible) {
                options.visible = isVisible
            }
            this.columnOption(column.index, options)
        }
    }
    changeSortOrder(columnIndex, sortOrder) {
        var options = {};
        var sortingOptions = this.option("sorting");
        var sortingMode = sortingOptions && sortingOptions.mode;
        var needResetSorting = "single" === sortingMode || !sortOrder;
        var allowSorting = "single" === sortingMode || "multiple" === sortingMode;
        var column = this._columns[columnIndex];
        if (allowSorting && column && column.allowSorting) {
            if (needResetSorting && !isDefined(column.groupIndex)) {
                each(this._columns, (function(index) {
                    if (index !== columnIndex && this.sortOrder) {
                        if (!isDefined(this.groupIndex)) {
                            delete this.sortOrder
                        }
                        delete this.sortIndex
                    }
                }))
            }
            if (isSortOrderValid(sortOrder)) {
                if (column.sortOrder !== sortOrder) {
                    options.sortOrder = sortOrder
                }
            } else if ("none" === sortOrder) {
                if (column.sortOrder) {
                    options.sortIndex = void 0;
                    options.sortOrder = void 0
                }
            } else {
                ! function(column) {
                    if ("ctrl" === sortOrder) {
                        if (!("sortOrder" in column && "sortIndex" in column)) {
                            return false
                        }
                        options.sortOrder = void 0;
                        options.sortIndex = void 0
                    } else if (isDefined(column.groupIndex) || isDefined(column.sortIndex)) {
                        options.sortOrder = "desc" === column.sortOrder ? "asc" : "desc"
                    } else {
                        options.sortOrder = "asc"
                    }
                    return true
                }(column)
            }
        }
        this.columnOption(column.index, options)
    }
    getSortDataSourceParameters(useLocalSelector) {
        var sortColumns = [];
        var sort = [];
        each(this._columns, (function() {
            if ((this.dataField || this.selector || this.calculateCellValue) && isDefined(this.sortIndex) && !isDefined(this.groupIndex)) {
                sortColumns[this.sortIndex] = this
            }
        }));
        each(sortColumns, (function() {
            var sortOrder = this && this.sortOrder;
            if (isSortOrderValid(sortOrder)) {
                var sortItem = {
                    selector: this.calculateSortValue || this.displayField || this.calculateDisplayValue || useLocalSelector && this.selector || this.dataField || this.calculateCellValue,
                    desc: "desc" === this.sortOrder
                };
                if (this.sortingMethod) {
                    sortItem.compare = this.sortingMethod.bind(this)
                }
                sort.push(sortItem)
            }
        }));
        return sort.length > 0 ? sort : null
    }
    getGroupDataSourceParameters(useLocalSelector) {
        var group = [];
        each(this.getGroupColumns(), (function() {
            var selector = this.calculateGroupValue || this.displayField || this.calculateDisplayValue || useLocalSelector && this.selector || this.dataField || this.calculateCellValue;
            if (selector) {
                var groupItem = {
                    selector: selector,
                    desc: "desc" === this.sortOrder,
                    isExpanded: !!this.autoExpandGroup
                };
                if (this.sortingMethod) {
                    groupItem.compare = this.sortingMethod.bind(this)
                }
                group.push(groupItem)
            }
        }));
        return group.length > 0 ? group : null
    }
    refresh(updateNewLookupsOnly) {
        var deferreds = [];
        each(this._columns, (function() {
            var {
                lookup: lookup
            } = this;
            if (lookup && !this.calculateDisplayValue) {
                if (updateNewLookupsOnly && lookup.valueMap) {
                    return
                }
                if (lookup.update) {
                    deferreds.push(lookup.update())
                }
            }
        }));
        return when.apply($, deferreds).done(resetColumnsCache.bind(null, this))
    }
    _updateColumnOptions(column, columnIndex) {
        column.selector = column.selector || function(data) {
            return column.calculateCellValue(data)
        };
        if (this._reinitAfterLookupChanges && this._previousColumns) {
            column.selector.columnIndex = columnIndex;
            column.selector.originalCallback = this._previousColumns[columnIndex].selector.originalCallback
        } else {
            column.selector.columnIndex = columnIndex;
            column.selector.originalCallback = column.selector
        }
        each(["calculateSortValue", "calculateGroupValue", "calculateDisplayValue"], (_, calculateCallbackName) => {
            var calculateCallback = column[calculateCallbackName];
            if (isFunction(calculateCallback)) {
                if (!calculateCallback.originalCallback) {
                    var context = {
                        column: column
                    };
                    column[calculateCallbackName] = function(data) {
                        return calculateCallback.call(context.column, data)
                    };
                    column[calculateCallbackName].originalCallback = calculateCallback;
                    column[calculateCallbackName].columnIndex = columnIndex;
                    column[calculateCallbackName].context = context
                } else {
                    column[calculateCallbackName].context.column = column
                }
            }
        });
        if (isString(column.calculateDisplayValue)) {
            column.displayField = column.calculateDisplayValue;
            column.calculateDisplayValue = compileGetter(column.displayField)
        }
        if (column.calculateDisplayValue) {
            column.displayValueMap = column.displayValueMap || {}
        }
        updateSerializers(column, column.dataType);
        var {
            lookup: lookup
        } = column;
        if (lookup) {
            updateSerializers(lookup, lookup.dataType)
        }
        var dataType = lookup ? lookup.dataType : column.dataType;
        if (dataType) {
            column.alignment = column.alignment || getAlignmentByDataType(dataType, this.option("rtlEnabled"));
            column.format = column.format || gridCoreUtils.getFormatByDataType(dataType);
            column.customizeText = column.customizeText || getCustomizeTextByDataType(dataType);
            column.defaultFilterOperations = column.defaultFilterOperations || !lookup && DATATYPE_OPERATIONS[dataType] || [];
            if (!isDefined(column.filterOperations)) {
                setFilterOperationsAsDefaultValues(column)
            }
            column.defaultFilterOperation = column.filterOperations && column.filterOperations[0] || "=";
            column.showEditorAlways = isDefined(column.showEditorAlways) ? column.showEditorAlways : "boolean" === dataType && !column.cellTemplate && !column.lookup
        }
    }
    updateColumnDataTypes(dataSource) {
        var that = this;
        var dateSerializationFormat = that.option("dateSerializationFormat");
        var firstItems = that._getFirstItems(dataSource);
        var isColumnDataTypesUpdated = false;
        each(that._columns, (index, column) => {
            var i;
            var value;
            var dataType;
            var lookupDataType;
            var valueDataType;
            var {
                lookup: lookup
            } = column;
            if (gridCoreUtils.isDateType(column.dataType) && void 0 === column.serializationFormat) {
                column.serializationFormat = dateSerializationFormat
            }
            if (lookup && gridCoreUtils.isDateType(lookup.dataType) && void 0 === column.serializationFormat) {
                lookup.serializationFormat = dateSerializationFormat
            }
            if (column.calculateCellValue && firstItems.length) {
                if (!column.dataType || lookup && !lookup.dataType) {
                    for (i = 0; i < firstItems.length; i++) {
                        value = column.calculateCellValue(firstItems[i]);
                        if (!column.dataType) {
                            valueDataType = getValueDataType(value);
                            dataType = dataType || valueDataType;
                            if (dataType && valueDataType && dataType !== valueDataType) {
                                dataType = "string"
                            }
                        }
                        if (lookup && !lookup.dataType) {
                            valueDataType = getValueDataType(gridCoreUtils.getDisplayValue(column, value, firstItems[i]));
                            lookupDataType = lookupDataType || valueDataType;
                            if (lookupDataType && valueDataType && lookupDataType !== valueDataType) {
                                lookupDataType = "string"
                            }
                        }
                    }
                    if (dataType || lookupDataType) {
                        if (dataType) {
                            column.dataType = dataType
                        }
                        if (lookup && lookupDataType) {
                            lookup.dataType = lookupDataType
                        }
                        isColumnDataTypesUpdated = true
                    }
                }
                if (void 0 === column.serializationFormat || lookup && void 0 === lookup.serializationFormat) {
                    for (i = 0; i < firstItems.length; i++) {
                        value = column.calculateCellValue(firstItems[i], true);
                        if (void 0 === column.serializationFormat) {
                            column.serializationFormat = getSerializationFormat(column.dataType, value)
                        }
                        if (lookup && void 0 === lookup.serializationFormat) {
                            lookup.serializationFormat = getSerializationFormat(lookup.dataType, lookup.calculateCellValue(value, true))
                        }
                    }
                }
            }
            that._updateColumnOptions(column, index)
        });
        return isColumnDataTypesUpdated
    }
    _customizeColumns(columns) {
        var customizeColumns = this.option("customizeColumns");
        if (customizeColumns) {
            var hasOwnerBand = columns.some(column => isObject(column.ownerBand));
            if (hasOwnerBand) {
                updateIndexes(this)
            }
            customizeColumns(columns);
            assignColumns(this, createColumnsFromOptions(this, columns))
        }
    }
    updateColumns(dataSource, forceApplying, isApplyingUserState) {
        if (!forceApplying) {
            this.updateSortingGrouping(dataSource)
        }
        if (!dataSource || dataSource.isLoaded()) {
            var sortParameters = dataSource ? dataSource.sort() || [] : this.getSortDataSourceParameters();
            var groupParameters = dataSource ? dataSource.group() || [] : this.getGroupDataSourceParameters();
            var filterParameters = null === dataSource || void 0 === dataSource ? void 0 : dataSource.lastLoadOptions().filter;
            if (!isApplyingUserState) {
                this._customizeColumns(this._columns)
            }
            updateIndexes(this);
            var columns = this._columns;
            return when(this.refresh(true)).always(() => {
                if (this._columns !== columns) {
                    return
                }
                this._updateChanges(dataSource, {
                    sorting: sortParameters,
                    grouping: groupParameters,
                    filtering: filterParameters
                });
                fireColumnsChanged(this)
            })
        }
    }
    _updateChanges(dataSource, parameters) {
        if (dataSource) {
            this.updateColumnDataTypes(dataSource);
            this._dataSourceApplied = true
        }
        if (!gridCoreUtils.equalSortParameters(parameters.sorting, this.getSortDataSourceParameters())) {
            updateColumnChanges(this, "sorting")
        }
        if (!gridCoreUtils.equalSortParameters(parameters.grouping, this.getGroupDataSourceParameters())) {
            updateColumnChanges(this, "grouping")
        }
        var dataController = this.getController("data");
        if (dataController && !gridCoreUtils.equalFilterParameters(parameters.filtering, dataController.getCombinedFilter())) {
            updateColumnChanges(this, "filtering")
        }
        updateColumnChanges(this, "columns")
    }
    updateSortingGrouping(dataSource, fromDataSource) {
        var that = this;
        var sortParameters;
        var isColumnsChanged;
        var updateSortGroupParameterIndexes = function(columns, sortParameters, indexParameterName) {
            each(columns, (index, column) => {
                delete column[indexParameterName];
                if (sortParameters) {
                    for (var i = 0; i < sortParameters.length; i++) {
                        var {
                            selector: selector
                        } = sortParameters[i];
                        var {
                            isExpanded: isExpanded
                        } = sortParameters[i];
                        if (selector === column.dataField || selector === column.name || selector === column.selector || selector === column.calculateCellValue || selector === column.calculateGroupValue || selector === column.calculateDisplayValue) {
                            if (fromDataSource) {
                                column.sortOrder = "sortOrder" in column ? column.sortOrder : sortParameters[i].desc ? "desc" : "asc"
                            } else {
                                column.sortOrder = column.sortOrder || (sortParameters[i].desc ? "desc" : "asc")
                            }
                            if (void 0 !== isExpanded) {
                                column.autoExpandGroup = isExpanded
                            }
                            column[indexParameterName] = i;
                            break
                        }
                    }
                }
            })
        };
        if (dataSource) {
            sortParameters = gridCoreUtils.normalizeSortingInfo(dataSource.sort());
            var groupParameters = gridCoreUtils.normalizeSortingInfo(dataSource.group());
            var columnsGroupParameters = that.getGroupDataSourceParameters();
            var columnsSortParameters = that.getSortDataSourceParameters();
            var groupingChanged = !gridCoreUtils.equalSortParameters(groupParameters, columnsGroupParameters, true);
            var groupExpandingChanged = !groupingChanged && !gridCoreUtils.equalSortParameters(groupParameters, columnsGroupParameters);
            if (!that._columns.length) {
                each(groupParameters, (index, group) => {
                    that._columns.push(group.selector)
                });
                each(sortParameters, (index, sort) => {
                    if (!isFunction(sort.selector)) {
                        that._columns.push(sort.selector)
                    }
                });
                assignColumns(that, createColumnsFromOptions(that, that._columns))
            }
            if ((fromDataSource || !columnsGroupParameters && !that._hasUserState) && (groupingChanged || groupExpandingChanged)) {
                that.__groupingUpdated = true;
                updateSortGroupParameterIndexes(that._columns, groupParameters, "groupIndex");
                if (fromDataSource) {
                    groupingChanged && updateColumnChanges(that, "grouping");
                    groupExpandingChanged && updateColumnChanges(that, "groupExpanding");
                    isColumnsChanged = true
                }
            }
            if ((fromDataSource || !columnsSortParameters && !that._hasUserState) && !gridCoreUtils.equalSortParameters(sortParameters, columnsSortParameters)) {
                that.__sortingUpdated = true;
                updateSortGroupParameterIndexes(that._columns, sortParameters, "sortIndex");
                if (fromDataSource) {
                    updateColumnChanges(that, "sorting");
                    isColumnsChanged = true
                }
            }
            if (isColumnsChanged) {
                fireColumnsChanged(that)
            }
        }
    }
    updateFilter(filter, remoteFiltering, columnIndex, filterValue) {
        if (!Array.isArray(filter)) {
            return filter
        }
        filter = extend([], filter);
        columnIndex = void 0 !== filter.columnIndex ? filter.columnIndex : columnIndex;
        filterValue = void 0 !== filter.filterValue ? filter.filterValue : filterValue;
        if (isString(filter[0]) && "!" !== filter[0]) {
            var column = this.columnOption(filter[0]);
            if (remoteFiltering) {
                if (config().forceIsoDateParsing && column && column.serializeValue && filter.length > 1) {
                    filter[filter.length - 1] = column.serializeValue(filter[filter.length - 1], "filter")
                }
            } else if (column && column.selector) {
                filter[0] = column.selector;
                filter[0].columnIndex = column.index
            }
        } else if (isFunction(filter[0])) {
            filter[0].columnIndex = columnIndex;
            filter[0].filterValue = filterValue;
            filter[0].selectedFilterOperation = filter.selectedFilterOperation
        }
        for (var i = 0; i < filter.length; i++) {
            filter[i] = this.updateFilter(filter[i], remoteFiltering, columnIndex, filterValue)
        }
        return filter
    }
    columnCount() {
        return this._columns ? this._columns.length : 0
    }
    columnOption(identifier, option, value, notFireEvent) {
        var that = this;
        var columns = that._columns.concat(that._commandColumns);
        var column = findColumn(columns, identifier);
        if (column) {
            if (1 === arguments.length) {
                return extend({}, column)
            }
            if (isString(option)) {
                if (2 === arguments.length) {
                    return columnOptionCore(that, column, option)
                }
                columnOptionCore(that, column, option, value, notFireEvent)
            } else if (isObject(option)) {
                each(option, (optionName, value) => {
                    columnOptionCore(that, column, optionName, value, notFireEvent)
                })
            }
            fireColumnsChanged(that)
        }
    }
    clearSorting() {
        var columnCount = this.columnCount();
        this.beginUpdate();
        for (var i = 0; i < columnCount; i++) {
            this.columnOption(i, "sortOrder", void 0);
            delete findColumn(this._columns, i).sortOrder
        }
        this.endUpdate()
    }
    clearGrouping() {
        var columnCount = this.columnCount();
        this.beginUpdate();
        for (var i = 0; i < columnCount; i++) {
            this.columnOption(i, "groupIndex", void 0)
        }
        this.endUpdate()
    }
    getVisibleIndex(index, rowIndex) {
        var columns = this.getVisibleColumns(rowIndex);
        for (var i = columns.length - 1; i >= 0; i--) {
            if (columns[i].index === index) {
                return i
            }
        }
        return -1
    }
    getVisibleIndexByColumn(column, rowIndex) {
        var visibleColumns = this.getVisibleColumns(rowIndex);
        var visibleColumn = visibleColumns.filter(col => col.index === column.index && col.command === column.command)[0];
        return visibleColumns.indexOf(visibleColumn)
    }
    getVisibleColumnIndex(id, rowIndex) {
        var index = this.columnOption(id, "index");
        return this.getVisibleIndex(index, rowIndex)
    }
    addColumn(options) {
        var column = createColumn(this, options);
        var index = this._columns.length;
        this._columns.push(column);
        if (column.isBand) {
            this._columns = createColumnsFromOptions(this, this._columns);
            column = this._columns[index]
        }
        column.added = options;
        updateIndexes(this, column);
        this.updateColumns(this._dataSource);
        this._checkColumns()
    }
    deleteColumn(id) {
        var column = this.columnOption(id);
        if (column && column.index >= 0) {
            convertOwnerBandToColumnReference(this._columns);
            this._columns.splice(column.index, 1);
            if (column.isBand) {
                var childIndexes = this.getChildrenByBandColumn(column.index).map(column => column.index);
                this._columns = this._columns.filter(column => childIndexes.indexOf(column.index) < 0)
            }
            updateIndexes(this);
            this.updateColumns(this._dataSource)
        }
    }
    addCommandColumn(options) {
        var commandColumn = this._commandColumns.filter(column => column.command === options.command)[0];
        if (!commandColumn) {
            commandColumn = options;
            this._commandColumns.push(commandColumn)
        }
    }
    getUserState() {
        var columns = this._columns;
        var result = [];
        var i;

        function handleStateField(index, value) {
            if (void 0 !== columns[i][value]) {
                result[i][value] = columns[i][value]
            }
        }
        for (i = 0; i < columns.length; i++) {
            result[i] = {};
            each(USER_STATE_FIELD_NAMES, handleStateField)
        }
        return result
    }
    setName(column) {
        column.name = column.name || column.dataField || column.type
    }
    setUserState(state) {
        var dataSource = this._dataSource;
        var ignoreColumnOptionNames = this.option("stateStoring.ignoreColumnOptionNames");
        null === state || void 0 === state ? void 0 : state.forEach(this.setName);
        if (!ignoreColumnOptionNames) {
            ignoreColumnOptionNames = [];
            var commonColumnSettings = this.getCommonSettings();
            if (!this.option("columnChooser.enabled")) {
                ignoreColumnOptionNames.push("visible")
            }
            if ("none" === this.option("sorting.mode")) {
                ignoreColumnOptionNames.push("sortIndex", "sortOrder")
            }
            if (!commonColumnSettings.allowGrouping) {
                ignoreColumnOptionNames.push("groupIndex")
            }
            if (!commonColumnSettings.allowFixing) {
                ignoreColumnOptionNames.push("fixed", "fixedPosition")
            }
            if (!commonColumnSettings.allowResizing) {
                ignoreColumnOptionNames.push("width", "visibleWidth")
            }
            var isFilterPanelHidden = !this.option("filterPanel.visible");
            if (!this.option("filterRow.visible") && isFilterPanelHidden) {
                ignoreColumnOptionNames.push("filterValue", "selectedFilterOperation")
            }
            if (!this.option("headerFilter.visible") && isFilterPanelHidden) {
                ignoreColumnOptionNames.push("filterValues", "filterType")
            }
        }
        this._columnsUserState = state;
        this._ignoreColumnOptionNames = ignoreColumnOptionNames;
        this._hasUserState = !!state;
        updateColumnChanges(this, "filtering");
        this.init(true);
        if (dataSource) {
            dataSource.sort(this.getSortDataSourceParameters());
            dataSource.group(this.getGroupDataSourceParameters())
        }
    }
    _checkColumns() {
        var usedNames = {};
        var hasEditableColumnWithoutName = false;
        var duplicatedNames = [];
        this._columns.forEach(column => {
            var _a;
            var {
                name: name
            } = column;
            var isBand = null === (_a = column.columns) || void 0 === _a ? void 0 : _a.length;
            var isEditable = column.allowEditing && (column.dataField || column.setCellValue) && !isBand;
            if (name) {
                if (usedNames[name]) {
                    duplicatedNames.push('"'.concat(name, '"'))
                }
                usedNames[name] = true
            } else if (isEditable) {
                hasEditableColumnWithoutName = true
            }
        });
        if (duplicatedNames.length) {
            errors.log("E1059", duplicatedNames.join(", "))
        }
        if (hasEditableColumnWithoutName) {
            errors.log("E1060")
        }
    }
    _createCalculatedColumnOptions(columnOptions, bandColumn) {
        var calculatedColumnOptions = {};
        var {
            dataField: dataField
        } = columnOptions;
        if (Array.isArray(columnOptions.columns) && columnOptions.columns.length || columnOptions.isBand) {
            calculatedColumnOptions.isBand = true;
            dataField = null
        }
        if (dataField) {
            if (isString(dataField)) {
                var getter = compileGetter(dataField);
                calculatedColumnOptions = {
                    caption: captionize(dataField),
                    calculateCellValue(data, skipDeserialization) {
                        var value = getter(data);
                        return this.deserializeValue && !skipDeserialization ? this.deserializeValue(value) : value
                    },
                    setCellValue: defaultSetCellValue,
                    parseValue(text) {
                        var result;
                        var parsedValue;
                        if ("number" === this.dataType) {
                            if (isString(text) && this.format) {
                                result = strictParseNumber(text.trim(), this.format)
                            } else if (isDefined(text) && isNumeric(text)) {
                                result = Number(text)
                            }
                        } else if ("boolean" === this.dataType) {
                            if (text === this.trueText) {
                                result = true
                            } else if (text === this.falseText) {
                                result = false
                            }
                        } else if (gridCoreUtils.isDateType(this.dataType)) {
                            parsedValue = dateLocalization.parse(text, this.format);
                            if (parsedValue) {
                                result = parsedValue
                            }
                        } else {
                            result = text
                        }
                        return result
                    }
                }
            }
            calculatedColumnOptions.allowFiltering = true
        } else {
            calculatedColumnOptions.allowFiltering = !!columnOptions.calculateFilterExpression
        }
        calculatedColumnOptions.calculateFilterExpression = function() {
            return filterUtils.defaultCalculateFilterExpression.apply(this, arguments)
        };
        calculatedColumnOptions.defaultFilterOperation = "=";
        calculatedColumnOptions.createFilterExpression = function(filterValue, selectedFilterOperation) {
            var result;
            if (this.calculateFilterExpression) {
                result = this.calculateFilterExpression.apply(this, arguments)
            }
            if (isFunction(result)) {
                result = [result, "=", true]
            }
            if (result) {
                result.columnIndex = this.index;
                result.filterValue = filterValue;
                result.selectedFilterOperation = selectedFilterOperation
            }
            return result
        };
        if (!dataField || !isString(dataField)) {
            extend(true, calculatedColumnOptions, {
                allowSorting: false,
                allowGrouping: false,
                calculateCellValue: () => null
            })
        }
        if (bandColumn) {
            calculatedColumnOptions.allowFixing = false
        }
        if (columnOptions.dataType) {
            calculatedColumnOptions.userDataType = columnOptions.dataType
        }
        if (columnOptions.selectedFilterOperation && !("defaultSelectedFilterOperation" in calculatedColumnOptions)) {
            calculatedColumnOptions.defaultSelectedFilterOperation = columnOptions.selectedFilterOperation
        }
        if (columnOptions.lookup) {
            calculatedColumnOptions.lookup = {
                calculateCellValue(value, skipDeserialization) {
                    if (this.valueExpr) {
                        value = this.valueMap && this.valueMap[value]
                    }
                    return this.deserializeValue && !skipDeserialization ? this.deserializeValue(value) : value
                },
                updateValueMap() {
                    this.valueMap = {};
                    if (this.items) {
                        var calculateValue = compileGetter(this.valueExpr);
                        var calculateDisplayValue = compileGetter(this.displayExpr);
                        for (var i = 0; i < this.items.length; i++) {
                            var item = this.items[i];
                            var displayValue = calculateDisplayValue(item);
                            this.valueMap[calculateValue(item)] = displayValue;
                            this.dataType = this.dataType || getValueDataType(displayValue)
                        }
                    }
                },
                update() {
                    var that = this;
                    var {
                        dataSource: dataSource
                    } = that;
                    if (dataSource) {
                        if (isFunction(dataSource) && !variableWrapper.isWrapped(dataSource)) {
                            dataSource = dataSource({})
                        }
                        if (isPlainObject(dataSource) || dataSource instanceof Store || Array.isArray(dataSource)) {
                            if (that.valueExpr) {
                                var dataSourceOptions = normalizeDataSourceOptions(dataSource);
                                dataSourceOptions.paginate = false;
                                dataSource = new DataSource(dataSourceOptions);
                                return dataSource.load().done(data => {
                                    that.items = data;
                                    that.updateValueMap && that.updateValueMap()
                                })
                            }
                        } else {
                            errors.log("E1016")
                        }
                    } else {
                        that.updateValueMap && that.updateValueMap()
                    }
                }
            }
        }
        calculatedColumnOptions.resizedCallbacks = Callbacks();
        if (columnOptions.resized) {
            calculatedColumnOptions.resizedCallbacks.add(columnOptions.resized.bind(columnOptions))
        }
        each(calculatedColumnOptions, optionName => {
            if (isFunction(calculatedColumnOptions[optionName]) && 0 !== optionName.indexOf("default")) {
                var defaultOptionName = "default".concat(optionName.charAt(0).toUpperCase()).concat(optionName.substr(1));
                calculatedColumnOptions[defaultOptionName] = calculatedColumnOptions[optionName]
            }
        });
        return calculatedColumnOptions
    }
    getRowCount() {
        this._rowCount = this._rowCount || getRowCount(this);
        return this._rowCount
    }
    getRowIndex(columnIndex, alwaysGetRowIndex) {
        var column = this._columns[columnIndex];
        var bandColumnsCache = this.getBandColumnsCache();
        return column && (alwaysGetRowIndex || column.visible && !(column.command || isDefined(column.groupIndex))) ? getParentBandColumns(columnIndex, bandColumnsCache.columnParentByIndex).length : 0
    }
    getChildrenByBandColumn(bandColumnIndex, onlyVisibleDirectChildren) {
        var bandColumnsCache = this.getBandColumnsCache();
        var result = getChildrenByBandColumn(bandColumnIndex, bandColumnsCache.columnChildrenByIndex, !onlyVisibleDirectChildren);
        if (onlyVisibleDirectChildren) {
            return result.filter(column => column.visible && !column.command).sort((column1, column2) => column1.visibleIndex - column2.visibleIndex)
        }
        return result
    }
    isParentBandColumn(columnIndex, bandColumnIndex) {
        var result = false;
        var column = this._columns[columnIndex];
        var bandColumnsCache = this.getBandColumnsCache();
        var parentBandColumns = column && getParentBandColumns(columnIndex, bandColumnsCache.columnParentByIndex);
        if (parentBandColumns) {
            each(parentBandColumns, (_, bandColumn) => {
                if (bandColumn.index === bandColumnIndex) {
                    result = true;
                    return false
                }
            })
        }
        return result
    }
    isParentColumnVisible(columnIndex) {
        var result = true;
        var bandColumnsCache = this.getBandColumnsCache();
        var bandColumns = columnIndex >= 0 && getParentBandColumns(columnIndex, bandColumnsCache.columnParentByIndex);
        bandColumns && each(bandColumns, (_, bandColumn) => {
            result = result && bandColumn.visible;
            return result
        });
        return result
    }
    getColumnId(column) {
        if (column.command && column.type === GROUP_COMMAND_COLUMN_NAME) {
            if (isCustomCommandColumn(this, column)) {
                return "type:".concat(column.type)
            }
            return "command:".concat(column.command)
        }
        return column.index
    }
    getCustomizeTextByDataType(dataType) {
        return getCustomizeTextByDataType(dataType)
    }
    getHeaderContentAlignment(columnAlignment) {
        var rtlEnabled = this.option("rtlEnabled");
        if (rtlEnabled) {
            return "left" === columnAlignment ? "right" : "left"
        }
        return columnAlignment
    }
}
export var columnsControllerModule = {
    defaultOptions: () => ({
        commonColumnSettings: {
            allowFiltering: true,
            allowHiding: true,
            allowSorting: true,
            allowEditing: true,
            encodeHtml: true,
            trueText: messageLocalization.format("dxDataGrid-trueText"),
            falseText: messageLocalization.format("dxDataGrid-falseText")
        },
        allowColumnReordering: false,
        allowColumnResizing: false,
        columnResizingMode: "nextColumn",
        columnMinWidth: void 0,
        columnWidth: void 0,
        adaptColumnWidthByRatio: true,
        columns: void 0,
        regenerateColumnsByVisibleItems: false,
        customizeColumns: null,
        dateSerializationFormat: void 0
    }),
    controllers: {
        columns: ColumnsController
    }
};
