/**
 * DevExtreme (esm/__internal/grids/grid_core/data_controller/m_data_controller.js)
 * Version: 22.1.13
 * Build date: Fri Feb 09 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
import $ from "../../../../core/renderer";
import {
    findChanges
} from "../../../../core/utils/array_compare";
import {
    deferRender,
    equalByValue
} from "../../../../core/utils/common";
import {
    Deferred,
    when
} from "../../../../core/utils/deferred";
import {
    extend
} from "../../../../core/utils/extend";
import {
    each
} from "../../../../core/utils/iterator";
import {
    isDefined,
    isObject
} from "../../../../core/utils/type";
import ArrayStore from "../../../../data/array_store";
import CustomStore from "../../../../data/custom_store";
import DataHelperMixin from "../../../../data_helper";
import errors from "../../../../ui/widget/ui.errors";
import modules from "../m_modules";
import gridCoreUtils from "../m_utils";
var changePaging = function(that, optionName, value) {
    var dataSource = that._dataSource;
    if (dataSource) {
        if (void 0 !== value) {
            var oldValue = that._getPagingOptionValue(optionName);
            if (oldValue !== value) {
                if ("pageSize" === optionName) {
                    dataSource.pageIndex(0)
                }
                dataSource[optionName](value);
                that._skipProcessingPagingChange = true;
                that.option("paging.".concat(optionName), value);
                that._skipProcessingPagingChange = false;
                var pageIndex = dataSource.pageIndex();
                that._isPaging = "pageIndex" === optionName;
                return dataSource["pageIndex" === optionName ? "load" : "reload"]().done(() => {
                    that._isPaging = false;
                    that.pageChanged.fire(pageIndex)
                })
            }
            return Deferred().resolve().promise()
        }
        return dataSource[optionName]()
    }
    return 0
};
var ControllerWithDataMixin = modules.Controller.inherit(DataHelperMixin);
export class DataController extends ControllerWithDataMixin {
    init() {
        var that = this;
        that._items = [];
        that._cachedProcessedItems = null;
        that._columnsController = this.getController("columns");
        that._isPaging = false;
        that._currentOperationTypes = null;
        that._dataChangedHandler = e => {
            that._currentOperationTypes = this._dataSource.operationTypes();
            that._handleDataChanged(e);
            that._currentOperationTypes = null
        };
        that._columnsChangedHandler = that._handleColumnsChanged.bind(that);
        that._loadingChangedHandler = that._handleLoadingChanged.bind(that);
        that._loadErrorHandler = that._handleLoadError.bind(that);
        that._customizeStoreLoadOptionsHandler = that._handleCustomizeStoreLoadOptions.bind(that);
        that._changingHandler = that._handleChanging.bind(that);
        that._dataPushedHandler = that._handleDataPushed.bind(that);
        that._columnsController.columnsChanged.add(that._columnsChangedHandler);
        that._isLoading = false;
        that._isCustomLoading = false;
        that._repaintChangesOnly = void 0;
        that._changes = [];
        that.createAction("onDataErrorOccurred");
        that.dataErrorOccurred.add(error => that.executeAction("onDataErrorOccurred", {
            error: error
        }));
        that._refreshDataSource()
    }
    _getPagingOptionValue(optionName) {
        return this._dataSource[optionName]()
    }
    callbackNames() {
        return ["changed", "loadingChanged", "dataErrorOccurred", "pageChanged", "dataSourceChanged", "pushed"]
    }
    callbackFlags(name) {
        if ("dataErrorOccurred" === name) {
            return {
                stopOnFalse: true
            }
        }
        return
    }
    publicMethods() {
        return ["beginCustomLoading", "endCustomLoading", "refresh", "filter", "clearFilter", "getCombinedFilter", "keyOf", "byKey", "getDataByKeys", "pageIndex", "pageSize", "pageCount", "totalCount", "_disposeDataSource", "getKeyByRowIndex", "getRowIndexByKey", "getDataSource", "getVisibleRows", "repaintRows"]
    }
    reset() {
        this._columnsController.reset();
        this._items = [];
        this._refreshDataSource()
    }
    _handleDataSourceChange(args) {
        if (args.value === args.previousValue || this.option("columns") && Array.isArray(args.value) && Array.isArray(args.previousValue)) {
            var isValueChanged = args.value !== args.previousValue;
            if (isValueChanged) {
                var store = this.store();
                if (store) {
                    store._array = args.value
                }
            }
            if (this.needToRefreshOnDataSourceChange(args)) {
                this.refresh(this.option("repaintChangesOnly"))
            }
            return true
        }
        return false
    }
    needToRefreshOnDataSourceChange(args) {
        return true
    }
    optionChanged(args) {
        var that = this;
        var dataSource;
        var changedPagingOptions;

        function handled() {
            args.handled = true
        }
        if ("dataSource" === args.name && args.name === args.fullName && this._handleDataSourceChange(args)) {
            handled();
            return
        }
        switch (args.name) {
            case "cacheEnabled":
            case "repaintChangesOnly":
            case "highlightChanges":
            case "loadingTimeout":
                handled();
                break;
            case "remoteOperations":
            case "keyExpr":
            case "dataSource":
            case "scrolling":
                handled();
                that.reset();
                break;
            case "paging":
                dataSource = that.dataSource();
                if (dataSource) {
                    changedPagingOptions = that._setPagingOptions(dataSource);
                    if (changedPagingOptions) {
                        var pageIndex = dataSource.pageIndex();
                        this._isPaging = changedPagingOptions.isPageIndexChanged;
                        dataSource.load().done(() => {
                            this._isPaging = false;
                            that.pageChanged.fire(pageIndex)
                        })
                    }
                }
                handled();
                break;
            case "rtlEnabled":
                that.reset();
                break;
            case "columns":
                dataSource = that.dataSource();
                if (dataSource && dataSource.isLoading() && args.name === args.fullName) {
                    this._useSortingGroupingFromColumns = true;
                    dataSource.load()
                }
                break;
            default:
                super.optionChanged(args)
        }
    }
    isReady() {
        return !this._isLoading
    }
    getDataSource() {
        return this._dataSource && this._dataSource._dataSource
    }
    getCombinedFilter(returnDataField) {
        return this.combinedFilter(void 0, returnDataField)
    }
    combinedFilter(filter, returnDataField) {
        if (!this._dataSource) {
            return filter
        }
        var combinedFilter = null !== filter && void 0 !== filter ? filter : this._dataSource.filter();
        var isColumnsTypesDefined = this._columnsController.isDataSourceApplied() || this._columnsController.isAllDataTypesDefined();
        if (isColumnsTypesDefined) {
            var additionalFilter = this._calculateAdditionalFilter();
            combinedFilter = additionalFilter ? gridCoreUtils.combineFilters([additionalFilter, combinedFilter]) : combinedFilter
        }
        var isRemoteFiltering = this._dataSource.remoteOperations().filtering || returnDataField;
        combinedFilter = this._columnsController.updateFilter(combinedFilter, isRemoteFiltering);
        return combinedFilter
    }
    waitReady() {
        if (this._updateLockCount) {
            this._readyDeferred = new Deferred;
            return this._readyDeferred
        }
        return when()
    }
    _endUpdateCore() {
        var changes = this._changes;
        if (changes.length) {
            this._changes = [];
            var repaintChangesOnly = changes.every(change => change.repaintChangesOnly);
            this.updateItems(1 === changes.length ? changes[0] : {
                repaintChangesOnly: repaintChangesOnly
            })
        }
        if (this._readyDeferred) {
            this._readyDeferred.resolve();
            this._readyDeferred = null
        }
    }
    _handleCustomizeStoreLoadOptions(e) {
        var _a;
        var columnsController = this._columnsController;
        var dataSource = this._dataSource;
        var {
            storeLoadOptions: storeLoadOptions
        } = e;
        if (e.isCustomLoading && !storeLoadOptions.isLoadingAll) {
            return
        }
        storeLoadOptions.filter = this.combinedFilter(storeLoadOptions.filter);
        if (1 === (null === (_a = storeLoadOptions.filter) || void 0 === _a ? void 0 : _a.length) && "!" === storeLoadOptions.filter[0]) {
            e.data = [];
            e.extra = e.extra || {};
            e.extra.totalCount = 0
        }
        if (!columnsController.isDataSourceApplied()) {
            columnsController.updateColumnDataTypes(dataSource)
        }
        this._columnsUpdating = true;
        columnsController.updateSortingGrouping(dataSource, !this._useSortingGroupingFromColumns);
        this._columnsUpdating = false;
        storeLoadOptions.sort = columnsController.getSortDataSourceParameters();
        storeLoadOptions.group = columnsController.getGroupDataSourceParameters();
        dataSource.sort(storeLoadOptions.sort);
        dataSource.group(storeLoadOptions.group);
        storeLoadOptions.sort = columnsController.getSortDataSourceParameters(!dataSource.remoteOperations().sorting);
        e.group = columnsController.getGroupDataSourceParameters(!dataSource.remoteOperations().grouping)
    }
    _handleColumnsChanged(e) {
        var that = this;
        var {
            changeTypes: changeTypes
        } = e;
        var {
            optionNames: optionNames
        } = e;
        var filterValue;
        var filterValues;
        var filterApplied;
        if (changeTypes.sorting || changeTypes.grouping) {
            if (that._dataSource && !that._columnsUpdating) {
                that._dataSource.group(that._columnsController.getGroupDataSourceParameters());
                that._dataSource.sort(that._columnsController.getSortDataSourceParameters());
                that.reload()
            }
        } else if (changeTypes.columns) {
            filterValues = that._columnsController.columnOption(e.columnIndex, "filterValues");
            if (optionNames.filterValues || optionNames.filterType && Array.isArray(filterValues) || optionNames.filterValue || optionNames.selectedFilterOperation || optionNames.allowFiltering) {
                filterValue = that._columnsController.columnOption(e.columnIndex, "filterValue");
                if (Array.isArray(filterValues) || void 0 === e.columnIndex || isDefined(filterValue) || !optionNames.selectedFilterOperation || optionNames.filterValue) {
                    that._applyFilter();
                    filterApplied = true
                }
            }
            if (!that._needApplyFilter && !gridCoreUtils.checkChanges(optionNames, ["width", "visibleWidth", "filterValue", "bufferedFilterValue", "selectedFilterOperation", "filterValues", "filterType"])) {
                that._columnsController.columnsChanged.add((function updateItemsHandler(change) {
                    var _a;
                    that._columnsController.columnsChanged.remove(updateItemsHandler);
                    that.updateItems({
                        repaintChangesOnly: false,
                        virtualColumnsScrolling: null === (_a = null === change || void 0 === change ? void 0 : change.changeTypes) || void 0 === _a ? void 0 : _a.virtualColumnsScrolling
                    })
                }))
            }
            if (isDefined(optionNames.visible)) {
                var column = that._columnsController.columnOption(e.columnIndex);
                if (column && (isDefined(column.filterValue) || isDefined(column.filterValues))) {
                    that._applyFilter();
                    filterApplied = true
                }
            }
        }
        if (!filterApplied && changeTypes.filtering) {
            that.reload()
        }
    }
    _handleDataChanged(e) {
        var that = this;
        var dataSource = that._dataSource;
        var columnsController = that._columnsController;
        var isAsyncDataSourceApplying = false;
        this._useSortingGroupingFromColumns = false;
        if (dataSource && !that._isDataSourceApplying) {
            that._isDataSourceApplying = true;
            when(that._columnsController.applyDataSource(dataSource)).done(() => {
                if (that._isLoading) {
                    that._handleLoadingChanged(false)
                }
                if (isAsyncDataSourceApplying && e && e.isDelayed) {
                    e.isDelayed = false
                }
                that._isDataSourceApplying = false;
                var needApplyFilter = that._needApplyFilter;
                that._needApplyFilter = false;
                if (needApplyFilter && !that._isAllDataTypesDefined && (additionalFilter = that._calculateAdditionalFilter(), additionalFilter && additionalFilter.length)) {
                    errors.log("W1005", that.component.NAME);
                    that._applyFilter()
                } else {
                    that.updateItems(e, true)
                }
                var additionalFilter
            }).fail(() => {
                that._isDataSourceApplying = false
            });
            if (that._isDataSourceApplying) {
                isAsyncDataSourceApplying = true;
                that._handleLoadingChanged(true)
            }
            that._needApplyFilter = !that._columnsController.isDataSourceApplied();
            that._isAllDataTypesDefined = columnsController.isAllDataTypesDefined()
        }
    }
    _handleLoadingChanged(isLoading) {
        this._isLoading = isLoading;
        this._fireLoadingChanged()
    }
    _handleLoadError(e) {
        this.dataErrorOccurred.fire(e)
    }
    _handleDataPushed(changes) {
        this.pushed.fire(changes)
    }
    fireError() {
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
            args[_key] = arguments[_key]
        }
        this.dataErrorOccurred.fire(errors.Error.apply(errors, args))
    }
    _setPagingOptions(dataSource) {
        var pageIndex = this.option("paging.pageIndex");
        var pageSize = this.option("paging.pageSize");
        var pagingEnabled = this.option("paging.enabled");
        var scrollingMode = this.option("scrolling.mode");
        var appendMode = "infinite" === scrollingMode;
        var virtualMode = "virtual" === scrollingMode;
        var paginate = pagingEnabled || virtualMode || appendMode;
        var isPaginateChanged = false;
        var isPageSizeChanged = false;
        var isPageIndexChanged = false;
        dataSource.requireTotalCount(!appendMode);
        if (void 0 !== pagingEnabled && dataSource.paginate() !== paginate) {
            dataSource.paginate(paginate);
            isPaginateChanged = true
        }
        if (void 0 !== pageSize && dataSource.pageSize() !== pageSize) {
            dataSource.pageSize(pageSize);
            isPageSizeChanged = true
        }
        if (void 0 !== pageIndex && dataSource.pageIndex() !== pageIndex) {
            dataSource.pageIndex(pageIndex);
            isPageIndexChanged = true
        }
        if (isPaginateChanged || isPageSizeChanged || isPageIndexChanged) {
            return {
                isPaginateChanged: isPaginateChanged,
                isPageSizeChanged: isPageSizeChanged,
                isPageIndexChanged: isPageIndexChanged
            }
        }
        return false
    }
    _getSpecificDataSourceOption() {
        var dataSource = this.option("dataSource");
        if (Array.isArray(dataSource)) {
            return {
                store: {
                    type: "array",
                    data: dataSource,
                    key: this.option("keyExpr")
                }
            }
        }
        return dataSource
    }
    _initDataSource() {
        var oldDataSource = this._dataSource;
        super._initDataSource();
        var dataSource = this._dataSource;
        this._useSortingGroupingFromColumns = true;
        this._cachedProcessedItems = null;
        if (dataSource) {
            var changedPagingOptions = this._setPagingOptions(dataSource);
            this._isPaging = null === changedPagingOptions || void 0 === changedPagingOptions ? void 0 : changedPagingOptions.isPageIndexChanged;
            this.setDataSource(dataSource)
        } else if (oldDataSource) {
            this.updateItems()
        }
    }
    _loadDataSource() {
        var that = this;
        var dataSource = that._dataSource;
        var result = new Deferred;
        when(this._columnsController.refresh(true)).always(() => {
            if (dataSource) {
                dataSource.load().done((function() {
                    that._isPaging = false;
                    result.resolve.apply(result, arguments)
                })).fail(result.reject)
            } else {
                result.resolve()
            }
        });
        return result.promise()
    }
    _beforeProcessItems(items) {
        return items.slice(0)
    }
    getRowIndexDelta() {
        return 0
    }
    getDataIndex(change) {
        var visibleItems = this._items;
        var lastVisibleItem = "append" === change.changeType && visibleItems.length > 0 ? visibleItems[visibleItems.length - 1] : null;
        return isDefined(null === lastVisibleItem || void 0 === lastVisibleItem ? void 0 : lastVisibleItem.dataIndex) ? lastVisibleItem.dataIndex + 1 : 0
    }
    _processItems(items, change) {
        var that = this;
        var rowIndexDelta = that.getRowIndexDelta();
        var {
            changeType: changeType
        } = change;
        var visibleColumns = that._columnsController.getVisibleColumns(null, "loadingAll" === changeType);
        var dataIndex = this.getDataIndex(change);
        var options = {
            visibleColumns: visibleColumns,
            dataIndex: dataIndex
        };
        var result = [];
        each(items, (index, item) => {
            if (isDefined(item)) {
                options.rowIndex = index - rowIndexDelta;
                item = that._processItem(item, options);
                result.push(item)
            }
        });
        return result
    }
    _processItem(item, options) {
        item = this._generateDataItem(item, options);
        item = this._processDataItem(item, options);
        item.dataIndex = options.dataIndex++;
        return item
    }
    _generateDataItem(data, options) {
        return {
            rowType: "data",
            data: data,
            key: this.keyOf(data)
        }
    }
    _processDataItem(dataItem, options) {
        dataItem.values = this.generateDataValues(dataItem.data, options.visibleColumns);
        return dataItem
    }
    generateDataValues(data, columns, isModified) {
        var values = [];
        var value;
        for (var i = 0; i < columns.length; i++) {
            var column = columns[i];
            value = isModified ? void 0 : null;
            if (!column.command) {
                if (column.calculateCellValue) {
                    value = column.calculateCellValue(data)
                } else if (column.dataField) {
                    value = data[column.dataField]
                }
            }
            values.push(value)
        }
        return values
    }
    _applyChange(change) {
        if ("update" === change.changeType) {
            this._applyChangeUpdate(change)
        } else if (this.items().length && change.repaintChangesOnly && "refresh" === change.changeType) {
            this._applyChangesOnly(change)
        } else if ("refresh" === change.changeType) {
            this._applyChangeFull(change)
        }
    }
    _applyChangeFull(change) {
        this._items = change.items.slice(0)
    }
    _getRowIndices(change) {
        var rowIndices = change.rowIndices.slice(0);
        var rowIndexDelta = this.getRowIndexDelta();
        rowIndices.sort((a, b) => a - b);
        for (var i = 0; i < rowIndices.length; i++) {
            var correctedRowIndex = rowIndices[i];
            if (change.allowInvisibleRowIndices) {
                correctedRowIndex += rowIndexDelta
            }
            if (correctedRowIndex < 0) {
                rowIndices.splice(i, 1);
                i--
            }
        }
        return rowIndices
    }
    _applyChangeUpdate(change) {
        var that = this;
        var {
            items: items
        } = change;
        var rowIndices = that._getRowIndices(change);
        var rowIndexDelta = that.getRowIndexDelta();
        var repaintChangesOnly = that.option("repaintChangesOnly");
        var prevIndex = -1;
        var rowIndexCorrection = 0;
        var changeType;
        change.items = [];
        change.rowIndices = [];
        change.columnIndices = [];
        change.changeTypes = [];
        var equalItems = function(item1, item2, strict) {
            var result = item1 && item2 && equalByValue(item1.key, item2.key);
            if (result && strict) {
                result = item1.rowType === item2.rowType && ("detail" !== item2.rowType || item1.isEditing === item2.isEditing)
            }
            return result
        };
        each(rowIndices, (index, rowIndex) => {
            var columnIndices;
            rowIndex += rowIndexCorrection + rowIndexDelta;
            if (prevIndex === rowIndex) {
                return
            }
            prevIndex = rowIndex;
            var oldItem = that._items[rowIndex];
            var oldNextItem = that._items[rowIndex + 1];
            var newItem = items[rowIndex];
            var newNextItem = items[rowIndex + 1];
            var strict = equalItems(oldItem, oldNextItem) || equalItems(newItem, newNextItem);
            if (newItem) {
                newItem.rowIndex = rowIndex;
                change.items.push(newItem)
            }
            if (oldItem && newItem && equalItems(oldItem, newItem, strict)) {
                changeType = "update";
                that._items[rowIndex] = newItem;
                if (oldItem.visible !== newItem.visible) {
                    change.items.splice(-1, 1, {
                        visible: newItem.visible
                    })
                } else if (repaintChangesOnly && !change.isFullUpdate) {
                    columnIndices = that._partialUpdateRow(oldItem, newItem, rowIndex - rowIndexDelta)
                }
            } else if (newItem && !oldItem || newNextItem && equalItems(oldItem, newNextItem, strict)) {
                changeType = "insert";
                that._items.splice(rowIndex, 0, newItem);
                rowIndexCorrection++
            } else if (oldItem && !newItem || oldNextItem && equalItems(newItem, oldNextItem, strict)) {
                changeType = "remove";
                that._items.splice(rowIndex, 1);
                rowIndexCorrection--;
                prevIndex = -1
            } else if (newItem) {
                changeType = "update";
                that._items[rowIndex] = newItem
            } else {
                return
            }
            change.rowIndices.push(rowIndex - rowIndexDelta);
            change.changeTypes.push(changeType);
            change.columnIndices.push(columnIndices)
        })
    }
    _isCellChanged(oldRow, newRow, visibleRowIndex, columnIndex, isLiveUpdate) {
        if (JSON.stringify(oldRow.values[columnIndex]) !== JSON.stringify(newRow.values[columnIndex])) {
            return true
        }

        function isCellModified(row, columnIndex) {
            return row.modifiedValues ? void 0 !== row.modifiedValues[columnIndex] : false
        }
        if (isCellModified(oldRow, columnIndex) !== isCellModified(newRow, columnIndex)) {
            return true
        }
        return false
    }
    _getChangedColumnIndices(oldItem, newItem, visibleRowIndex, isLiveUpdate) {
        var columnIndices;
        if (oldItem.rowType === newItem.rowType) {
            if ("group" !== newItem.rowType && "groupFooter" !== newItem.rowType) {
                columnIndices = [];
                if ("detail" !== newItem.rowType) {
                    for (var columnIndex = 0; columnIndex < oldItem.values.length; columnIndex++) {
                        if (this._isCellChanged(oldItem, newItem, visibleRowIndex, columnIndex, isLiveUpdate)) {
                            columnIndices.push(columnIndex)
                        }
                    }
                }
            }
            if ("group" === newItem.rowType && newItem.isExpanded === oldItem.isExpanded && oldItem.cells) {
                columnIndices = oldItem.cells.map((cell, index) => {
                    var _a;
                    return "groupExpand" !== (null === (_a = cell.column) || void 0 === _a ? void 0 : _a.type) ? index : -1
                }).filter(index => index >= 0)
            }
        }
        return columnIndices
    }
    _partialUpdateRow(oldItem, newItem, visibleRowIndex, isLiveUpdate) {
        var changedColumnIndices = this._getChangedColumnIndices(oldItem, newItem, visibleRowIndex, isLiveUpdate);
        if ((null === changedColumnIndices || void 0 === changedColumnIndices ? void 0 : changedColumnIndices.length) && this.option("dataRowTemplate")) {
            changedColumnIndices = void 0
        }
        if (changedColumnIndices) {
            oldItem.cells && oldItem.cells.forEach((cell, columnIndex) => {
                var isCellChanged = changedColumnIndices.indexOf(columnIndex) >= 0;
                if (!isCellChanged && cell && cell.update) {
                    cell.update(newItem)
                }
            });
            newItem.update = oldItem.update;
            newItem.watch = oldItem.watch;
            newItem.cells = oldItem.cells;
            if (isLiveUpdate) {
                newItem.oldValues = oldItem.values
            }
            oldItem.update && oldItem.update(newItem)
        }
        return changedColumnIndices
    }
    _isItemEquals(item1, item2) {
        var _a, _b, _c, _d;
        if (JSON.stringify(item1.values) !== JSON.stringify(item2.values)) {
            return false
        }
        if (["modified", "isNewRow", "removed", "isEditing"].some(field => item1[field] !== item2[field])) {
            return false
        }
        if ("group" === item1.rowType || "groupFooter" === item1.rowType) {
            var expandedMatch = item1.isExpanded === item2.isExpanded;
            var summaryCellsMatch = JSON.stringify(item1.summaryCells) === JSON.stringify(item2.summaryCells);
            var continuationMatch = (null === (_a = item1.data) || void 0 === _a ? void 0 : _a.isContinuation) === (null === (_b = item2.data) || void 0 === _b ? void 0 : _b.isContinuation) && (null === (_c = item1.data) || void 0 === _c ? void 0 : _c.isContinuationOnNextPage) === (null === (_d = item2.data) || void 0 === _d ? void 0 : _d.isContinuationOnNextPage);
            if (!expandedMatch || !summaryCellsMatch || !continuationMatch) {
                return false
            }
        }
        return true
    }
    _applyChangesOnly(change) {
        var _a;
        var rowIndices = [];
        var columnIndices = [];
        var changeTypes = [];
        var items = [];
        var newIndexByKey = {};
        var isLiveUpdate = null !== (_a = null === change || void 0 === change ? void 0 : change.isLiveUpdate) && void 0 !== _a ? _a : true;

        function getRowKey(row) {
            if (row) {
                return "".concat(row.rowType, ",").concat(JSON.stringify(row.key))
            }
            return
        }
        var currentItems = this._items;
        var oldItems = currentItems.slice();
        change.items.forEach((item, index) => {
            var key = getRowKey(item);
            newIndexByKey[key] = index;
            item.rowIndex = index
        });
        var result = findChanges(oldItems, change.items, getRowKey, (item1, item2) => {
            if (!this._isItemEquals(item1, item2)) {
                return false
            }
            if (item1.cells) {
                item1.update && item1.update(item2);
                item1.cells.forEach(cell => {
                    if (cell && cell.update) {
                        cell.update(item2, true)
                    }
                })
            }
            return true
        });
        if (!result) {
            this._applyChangeFull(change);
            return
        }
        result.forEach(change => {
            switch (change.type) {
                case "update":
                    var {
                        index: index
                    } = change;
                    var newItem = change.data;
                    var {
                        oldItem: oldItem
                    } = change;
                    var changedColumnIndices = this._partialUpdateRow(oldItem, newItem, index, isLiveUpdate);
                    rowIndices.push(index);
                    changeTypes.push("update");
                    items.push(newItem);
                    currentItems[index] = newItem;
                    columnIndices.push(changedColumnIndices);
                    break;
                case "insert":
                    rowIndices.push(change.index);
                    changeTypes.push("insert");
                    items.push(change.data);
                    columnIndices.push(void 0);
                    currentItems.splice(change.index, 0, change.data);
                    break;
                case "remove":
                    rowIndices.push(change.index);
                    changeTypes.push("remove");
                    currentItems.splice(change.index, 1);
                    items.push(change.oldItem);
                    columnIndices.push(void 0)
            }
        });
        change.repaintChangesOnly = true;
        change.changeType = "update";
        change.rowIndices = rowIndices;
        change.columnIndices = columnIndices;
        change.changeTypes = changeTypes;
        change.items = items;
        if (oldItems.length) {
            change.isLiveUpdate = true
        }
        this._correctRowIndices(rowIndex => {
            var oldRowIndexOffset = this._rowIndexOffset || 0;
            var rowIndexOffset = this.getRowIndexOffset();
            var oldItem = oldItems[rowIndex - oldRowIndexOffset];
            var key = getRowKey(oldItem);
            var newVisibleRowIndex = newIndexByKey[key];
            return newVisibleRowIndex >= 0 ? newVisibleRowIndex + rowIndexOffset - rowIndex : 0
        })
    }
    _correctRowIndices(rowIndex) {}
    _afterProcessItems(items, change) {
        return items
    }
    _updateItemsCore(change) {
        var items;
        var dataSource = this._dataSource;
        var changeType = change.changeType || "refresh";
        change.changeType = changeType;
        if (dataSource) {
            var cachedProcessedItems = this._cachedProcessedItems;
            if (change.useProcessedItemsCache && cachedProcessedItems) {
                items = cachedProcessedItems
            } else {
                items = change.items || dataSource.items();
                items = this._beforeProcessItems(items);
                items = this._processItems(items, change);
                this._cachedProcessedItems = items
            }
            items = this._afterProcessItems(items, change);
            change.items = items;
            var oldItems = this._items.length === items.length && this._items;
            this._applyChange(change);
            var rowIndexDelta = this.getRowIndexDelta();
            each(this._items, (index, item) => {
                var _a;
                item.rowIndex = index - rowIndexDelta;
                if (oldItems) {
                    item.cells = null !== (_a = oldItems[index].cells) && void 0 !== _a ? _a : []
                }
                var newItem = items[index];
                if (newItem) {
                    item.loadIndex = newItem.loadIndex
                }
            });
            this._rowIndexOffset = this.getRowIndexOffset()
        } else {
            this._items = []
        }
    }
    _handleChanging(e) {
        var rows = this.getVisibleRows();
        var dataSource = this.dataSource();
        if (dataSource) {
            e.changes.forEach(change => {
                if ("insert" === change.type && change.index >= 0) {
                    var dataIndex = 0;
                    for (var i = 0; i < change.index; i++) {
                        var row = rows[i];
                        if (row && ("data" === row.rowType || "group" === row.rowType)) {
                            dataIndex++
                        }
                    }
                    change.index = dataIndex
                }
            })
        }
    }
    updateItems(change, isDataChanged) {
        var _a;
        change = change || {};
        if (void 0 !== this._repaintChangesOnly) {
            change.repaintChangesOnly = null !== (_a = change.repaintChangesOnly) && void 0 !== _a ? _a : this._repaintChangesOnly;
            change.needUpdateDimensions = change.needUpdateDimensions || this._needUpdateDimensions
        } else if (change.changes) {
            change.repaintChangesOnly = this.option("repaintChangesOnly")
        } else if (isDataChanged) {
            var operationTypes = this.dataSource().operationTypes();
            change.repaintChangesOnly = operationTypes && !operationTypes.grouping && !operationTypes.filtering && this.option("repaintChangesOnly");
            change.isDataChanged = true;
            if (operationTypes && (operationTypes.reload || operationTypes.paging || operationTypes.groupExpanding)) {
                change.needUpdateDimensions = true
            }
        }
        if (this._updateLockCount && !change.cancel) {
            this._changes.push(change);
            return
        }
        this._updateItemsCore(change);
        if (change.cancel) {
            return
        }
        this._fireChanged(change)
    }
    loadingOperationTypes() {
        var dataSource = this.dataSource();
        return dataSource && dataSource.loadingOperationTypes() || {}
    }
    _fireChanged(change) {
        if (this._currentOperationTypes) {
            change.operationTypes = this._currentOperationTypes;
            this._currentOperationTypes = null
        }
        deferRender(() => {
            this.changed.fire(change)
        })
    }
    isLoading() {
        return this._isLoading || this._isCustomLoading
    }
    _fireLoadingChanged() {
        this.loadingChanged.fire(this.isLoading(), this._loadingText)
    }
    _calculateAdditionalFilter() {
        return null
    }
    _applyFilter() {
        var dataSource = this._dataSource;
        if (dataSource) {
            dataSource.pageIndex(0);
            this._isFilterApplying = true;
            return this.reload().done(() => {
                if (this._isFilterApplying) {
                    this.pageChanged.fire()
                }
            })
        }
    }
    resetFilterApplying() {
        this._isFilterApplying = false
    }
    filter(filterExpr) {
        var dataSource = this._dataSource;
        var filter = dataSource && dataSource.filter();
        if (0 === arguments.length) {
            return filter
        }
        filterExpr = arguments.length > 1 ? Array.prototype.slice.call(arguments, 0) : filterExpr;
        if (gridCoreUtils.equalFilterParameters(filter, filterExpr)) {
            return
        }
        if (dataSource) {
            dataSource.filter(filterExpr)
        }
        this._applyFilter()
    }
    clearFilter(filterName) {
        var columnsController = this._columnsController;
        var clearColumnOption = function(optionName) {
            var columnCount = columnsController.columnCount();
            for (var index = 0; index < columnCount; index++) {
                columnsController.columnOption(index, optionName, void 0)
            }
        };
        this.component.beginUpdate();
        if (arguments.length > 0) {
            switch (filterName) {
                case "dataSource":
                    this.filter(null);
                    break;
                case "search":
                    this.searchByText("");
                    break;
                case "header":
                    clearColumnOption("filterValues");
                    break;
                case "row":
                    clearColumnOption("filterValue")
            }
        } else {
            this.filter(null);
            this.searchByText("");
            clearColumnOption("filterValue");
            clearColumnOption("bufferedFilterValue");
            clearColumnOption("filterValues")
        }
        this.component.endUpdate()
    }
    _fireDataSourceChanged() {
        var that = this;
        that.changed.add((function changedHandler() {
            that.changed.remove(changedHandler);
            that.dataSourceChanged.fire()
        }))
    }
    _getDataSourceAdapter() {}
    _createDataSourceAdapterCore(dataSource, remoteOperations) {
        var dataSourceAdapterProvider = this._getDataSourceAdapter();
        var dataSourceAdapter = dataSourceAdapterProvider.create(this.component);
        dataSourceAdapter.init(dataSource, remoteOperations);
        return dataSourceAdapter
    }
    isLocalStore() {
        var store = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : this.store();
        return store instanceof ArrayStore
    }
    isCustomStore(store) {
        store = store || this.store();
        return store instanceof CustomStore
    }
    _createDataSourceAdapter(dataSource) {
        var remoteOperations = this.option("remoteOperations");
        var store = dataSource.store();
        var enabledRemoteOperations = {
            filtering: true,
            sorting: true,
            paging: true,
            grouping: true,
            summary: true
        };
        if (isObject(remoteOperations) && remoteOperations.groupPaging) {
            remoteOperations = extend({}, enabledRemoteOperations, remoteOperations)
        }
        if ("auto" === remoteOperations) {
            remoteOperations = this.isLocalStore(store) || this.isCustomStore(store) ? {} : {
                filtering: true,
                sorting: true,
                paging: true
            }
        }
        if (true === remoteOperations) {
            remoteOperations = enabledRemoteOperations
        }
        return this._createDataSourceAdapterCore(dataSource, remoteOperations)
    }
    setDataSource(dataSource) {
        var oldDataSource = this._dataSource;
        if (!dataSource && oldDataSource) {
            oldDataSource.cancelAll();
            oldDataSource.changed.remove(this._dataChangedHandler);
            oldDataSource.loadingChanged.remove(this._loadingChangedHandler);
            oldDataSource.loadError.remove(this._loadErrorHandler);
            oldDataSource.customizeStoreLoadOptions.remove(this._customizeStoreLoadOptionsHandler);
            oldDataSource.changing.remove(this._changingHandler);
            oldDataSource.pushed.remove(this._dataPushedHandler);
            oldDataSource.dispose(this._isSharedDataSource)
        }
        if (dataSource) {
            dataSource = this._createDataSourceAdapter(dataSource)
        }
        this._dataSource = dataSource;
        if (dataSource) {
            this._fireDataSourceChanged();
            this._isLoading = !dataSource.isLoaded();
            this._needApplyFilter = true;
            this._isAllDataTypesDefined = this._columnsController.isAllDataTypesDefined();
            dataSource.changed.add(this._dataChangedHandler);
            dataSource.loadingChanged.add(this._loadingChangedHandler);
            dataSource.loadError.add(this._loadErrorHandler);
            dataSource.customizeStoreLoadOptions.add(this._customizeStoreLoadOptionsHandler);
            dataSource.changing.add(this._changingHandler);
            dataSource.pushed.add(this._dataPushedHandler)
        }
    }
    items(byLoaded) {
        return this._items
    }
    isEmpty() {
        return !this.items().length
    }
    pageCount() {
        return this._dataSource ? this._dataSource.pageCount() : 1
    }
    dataSource() {
        return this._dataSource
    }
    store() {
        var dataSource = this._dataSource;
        return dataSource && dataSource.store()
    }
    loadAll(data) {
        var that = this;
        var d = new Deferred;
        var dataSource = that._dataSource;
        if (dataSource) {
            if (data) {
                var options = {
                    data: data,
                    isCustomLoading: true,
                    storeLoadOptions: {
                        isLoadingAll: true
                    },
                    loadOptions: {
                        filter: that.getCombinedFilter(),
                        group: dataSource.group(),
                        sort: dataSource.sort()
                    }
                };
                dataSource._handleDataLoaded(options);
                when(options.data).done(data => {
                    var _a;
                    data = that._beforeProcessItems(data);
                    d.resolve(that._processItems(data, {
                        changeType: "loadingAll"
                    }), null === (_a = options.extra) || void 0 === _a ? void 0 : _a.summary)
                }).fail(d.reject)
            } else if (!dataSource.isLoading()) {
                var loadOptions = extend({}, dataSource.loadOptions(), {
                    isLoadingAll: true,
                    requireTotalCount: false
                });
                dataSource.load(loadOptions).done((items, extra) => {
                    items = that._beforeProcessItems(items);
                    items = that._processItems(items, {
                        changeType: "loadingAll"
                    });
                    d.resolve(items, extra && extra.summary)
                }).fail(d.reject)
            } else {
                d.reject()
            }
        } else {
            d.resolve([])
        }
        return d
    }
    getKeyByRowIndex(rowIndex, byLoaded) {
        var item = this.items(byLoaded)[rowIndex];
        if (item) {
            return item.key
        }
    }
    getRowIndexByKey(key, byLoaded) {
        return gridCoreUtils.getIndexByKey(key, this.items(byLoaded))
    }
    keyOf(data) {
        var store = this.store();
        if (store) {
            return store.keyOf(data)
        }
    }
    byKey(key) {
        var store = this.store();
        var rowIndex = this.getRowIndexByKey(key);
        var result;
        if (!store) {
            return
        }
        if (rowIndex >= 0) {
            result = (new Deferred).resolve(this.items()[rowIndex].data)
        }
        return result || store.byKey(key)
    }
    key() {
        var store = this.store();
        if (store) {
            return store.key()
        }
    }
    getRowIndexOffset() {
        return 0
    }
    getDataByKeys(rowKeys) {
        var that = this;
        var result = new Deferred;
        var deferreds = [];
        var data = [];
        each(rowKeys, (index, key) => {
            deferreds.push(that.byKey(key).done(keyData => {
                data[index] = keyData
            }))
        });
        when.apply($, deferreds).always(() => {
            result.resolve(data)
        });
        return result
    }
    pageIndex(value) {
        return changePaging(this, "pageIndex", value)
    }
    pageSize(value) {
        return changePaging(this, "pageSize", value)
    }
    beginCustomLoading(messageText) {
        this._isCustomLoading = true;
        this._loadingText = messageText || "";
        this._fireLoadingChanged()
    }
    endCustomLoading() {
        this._isCustomLoading = false;
        this._loadingText = void 0;
        this._fireLoadingChanged()
    }
    refresh(options) {
        if (true === options) {
            options = {
                reload: true,
                changesOnly: true
            }
        } else if (!options) {
            options = {
                lookup: true,
                selection: true,
                reload: true
            }
        }
        var that = this;
        var dataSource = that.getDataSource();
        var {
            changesOnly: changesOnly
        } = options;
        var d = new Deferred;
        var customizeLoadResult = function() {
            that._repaintChangesOnly = !!changesOnly
        };
        when(!options.lookup || that._columnsController.refresh()).always(() => {
            if (options.load || options.reload) {
                dataSource && dataSource.on("customizeLoadResult", customizeLoadResult);
                when(that.reload(options.reload, changesOnly)).always(() => {
                    dataSource && dataSource.off("customizeLoadResult", customizeLoadResult);
                    that._repaintChangesOnly = void 0
                }).done(d.resolve).fail(d.reject)
            } else {
                that.updateItems({
                    repaintChangesOnly: options.changesOnly
                });
                d.resolve()
            }
        });
        return d.promise()
    }
    getVisibleRows() {
        return this.items()
    }
    _disposeDataSource() {
        this.setDataSource(null)
    }
    dispose() {
        this._disposeDataSource();
        super.dispose()
    }
    repaintRows(rowIndexes, changesOnly) {
        rowIndexes = Array.isArray(rowIndexes) ? rowIndexes : [rowIndexes];
        if (rowIndexes.length > 1 || isDefined(rowIndexes[0])) {
            this.updateItems({
                changeType: "update",
                rowIndices: rowIndexes,
                isFullUpdate: !changesOnly
            })
        }
    }
    skipProcessingPagingChange(fullName) {
        return this._skipProcessingPagingChange && ("paging.pageIndex" === fullName || "paging.pageSize" === fullName)
    }
    getUserState() {
        return {
            searchText: this.option("searchPanel.text"),
            pageIndex: this.pageIndex(),
            pageSize: this.pageSize()
        }
    }
    getCachedStoreData() {
        return this._dataSource && this._dataSource.getCachedStoreData()
    }
    isLastPageLoaded() {
        var pageIndex = this.pageIndex();
        var pageCount = this.pageCount();
        return pageIndex === pageCount - 1
    }
    load() {
        var _a;
        return null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.load()
    }
    reload(reload, changesOnly) {
        var _a;
        return null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.reload(reload, changesOnly)
    }
    push() {
        var _a;
        return null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.push(...arguments)
    }
    itemsCount() {
        var _a;
        return this._dataSource ? null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.itemsCount() : 0
    }
    totalItemsCount() {
        var _a;
        return this._dataSource ? null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.totalItemsCount() : 0
    }
    hasKnownLastPage() {
        var _a;
        return this._dataSource ? null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.hasKnownLastPage() : true
    }
    isLoaded() {
        var _a;
        return this._dataSource ? null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.isLoaded() : true
    }
    totalCount() {
        var _a;
        return this._dataSource ? null === (_a = this._dataSource) || void 0 === _a ? void 0 : _a.totalCount() : 0
    }
}
export var dataControllerModule = {
    defaultOptions: () => ({
        loadingTimeout: 0,
        dataSource: null,
        cacheEnabled: true,
        repaintChangesOnly: false,
        highlightChanges: false,
        onDataErrorOccurred: null,
        remoteOperations: "auto",
        paging: {
            enabled: true,
            pageSize: void 0,
            pageIndex: void 0
        }
    }),
    controllers: {
        data: DataController
    }
};
