/**
 * DevExtreme (cjs/__internal/grids/pivot_grid/data_controller/m_data_controller.js)
 * Version: 24.1.7-build-24272-1937
 * Build date: Sat Sep 28 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.default = exports.DataController__internals = exports.DataController = void 0;
var _class = _interopRequireDefault(require("../../../../core/class"));
var _callbacks = _interopRequireDefault(require("../../../../core/utils/callbacks"));
var _common = require("../../../../core/utils/common");
var _deferred = require("../../../../core/utils/deferred");
var _extend = require("../../../../core/utils/extend");
var _iterator = require("../../../../core/utils/iterator");
var _string = require("../../../../core/utils/string");
var _type = require("../../../../core/utils/type");
var _m_state_storing_core = _interopRequireDefault(require("../../../grids/grid_core/state_storing/m_state_storing_core"));
var _m_virtual_columns_core = require("../../../grids/grid_core/virtual_columns/m_virtual_columns_core");
var _m_virtual_scrolling_core = _interopRequireDefault(require("../../../grids/grid_core/virtual_scrolling/m_virtual_scrolling_core"));
var _m_data_source = require("../data_source/m_data_source");
var _m_widget_utils = require("../m_widget_utils");

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    }
}
const math = Math;
const GRAND_TOTAL_TYPE = "GT";
const TOTAL_TYPE = "T";
const DATA_TYPE = "D";
const NOT_AVAILABLE = "#N/A";
const CHANGING_DURATION_IF_PAGINATE = 300;
const proxyMethod = function(instance, methodName, defaultResult) {
    if (!instance[methodName]) {
        instance[methodName] = function() {
            const dataSource = this._dataSource;
            return dataSource ? dataSource[methodName].apply(dataSource, arguments) : defaultResult
        }
    }
};
const DataController = exports.DataController = _class.default.inherit(function() {
    function formatCellValue(value, dataField, errorText) {
        return "#N/A" === value ? errorText : (0, _m_widget_utils.formatValue)(value, dataField)
    }
    const createHeaderInfo = function() {
        const addInfoItem = function(info, options) {
            const breadth = options.lastIndex - options.index || 1;
            const itemInfo = function(headerItem, breadth, isHorizontal, isTree) {
                const infoItem = {
                    type: headerItem.type,
                    text: headerItem.text
                };
                if (headerItem.path) {
                    infoItem.path = headerItem.path
                }
                if (headerItem.width) {
                    infoItem.width = headerItem.width
                }
                if ((0, _type.isDefined)(headerItem.wordWrapEnabled)) {
                    infoItem.wordWrapEnabled = headerItem.wordWrapEnabled
                }
                if (headerItem.isLast) {
                    infoItem.isLast = true
                }
                if (headerItem.sorted) {
                    infoItem.sorted = true
                }
                if (headerItem.isMetric) {
                    infoItem.dataIndex = headerItem.dataIndex
                }
                if ((0, _type.isDefined)(headerItem.expanded)) {
                    infoItem.expanded = headerItem.expanded
                }
                if (breadth > 1) {
                    infoItem[isHorizontal ? "colspan" : "rowspan"] = breadth
                }
                if (headerItem.depthSize && headerItem.depthSize > 1) {
                    infoItem[isHorizontal ? "rowspan" : "colspan"] = headerItem.depthSize
                }
                if (headerItem.index >= 0) {
                    infoItem.dataSourceIndex = headerItem.index
                }
                if (isTree && headerItem.children && headerItem.children.length && !headerItem.children[0].isMetric) {
                    infoItem.width = null;
                    infoItem.isWhiteSpace = true
                }
                return infoItem
            }(options.headerItem, breadth, options.isHorizontal, options.isTree);
            ! function(info, infoItem, itemIndex, depthIndex, isHorizontal) {
                const index = isHorizontal ? depthIndex : itemIndex;
                while (!info[index]) {
                    info.push([])
                }
                if (isHorizontal) {
                    info[index].push(infoItem)
                } else {
                    info[index].unshift(infoItem)
                }
            }(info, itemInfo, options.index, options.depth, options.isHorizontal);
            if (!options.headerItem.children || 0 === options.headerItem.children.length) {
                return options.lastIndex + 1
            }
            return options.lastIndex
        };
        const getViewHeaderItems = function(headerItems, headerDescriptions, cellDescriptions, depthSize, options) {
            const cellDescriptionsCount = cellDescriptions.length;
            const viewHeaderItems = function(headerItems, headerDescriptions) {
                const headerDescriptionsCount = headerDescriptions && headerDescriptions.length || 0;
                const childrenStack = [];
                const d = new _deferred.Deferred;
                let headerItem;
                (0, _deferred.when)((0, _m_widget_utils.foreachTreeAsync)(headerItems, ((items, index) => {
                    const item = items[0];
                    const path = (0, _m_widget_utils.createPath)(items);
                    headerItem = createHeaderItem(childrenStack, path.length, index);
                    headerItem.type = "D";
                    headerItem.value = item.value;
                    headerItem.path = path;
                    headerItem.text = item.text;
                    headerItem.index = item.index;
                    headerItem.displayText = item.displayText;
                    headerItem.key = item.key;
                    headerItem.isEmpty = item.isEmpty;
                    if (path.length < headerDescriptionsCount && (!item.children || 0 !== item.children.length)) {
                        headerItem.expanded = !!item.children
                    }
                }))).done((() => {
                    d.resolve(createHeaderItem(childrenStack, 0, 0).children || [])
                }));
                return d
            }(headerItems, headerDescriptions);
            const {
                dataFields: dataFields
            } = options;
            const d = new _deferred.Deferred;
            (0, _deferred.when)(viewHeaderItems).done((viewHeaderItems => {
                options.notifyProgress(.5);
                if (options.showGrandTotals) {
                    viewHeaderItems[!options.showTotalsPrior ? "push" : "unshift"]({
                        type: "GT",
                        isEmpty: options.isEmptyGrandTotal
                    })
                }
                const hideTotals = false === options.showTotals || dataFields.length > 0 && dataFields.length === options.hiddenTotals.length;
                const hideData = dataFields.length > 0 && options.hiddenValues.length === dataFields.length;
                if (hideData && hideTotals) {
                    depthSize = 1
                }
                if (!hideTotals || "tree" === options.layout) {
                    ! function(headerItems, headerDescriptions, showTotalsPrior, isTree) {
                        showTotalsPrior = showTotalsPrior || isTree;
                        (0, _m_widget_utils.foreachTree)(headerItems, ((items, index) => {
                            const item = items[0];
                            const parentChildren = (items[1] ? items[1].children : headerItems) || [];
                            const dataField = headerDescriptions[items.length - 1];
                            if ("D" === item.type && item.expanded && (false !== dataField.showTotals || isTree)) {
                                -1 !== index && parentChildren.splice(showTotalsPrior ? index : index + 1, 0, (0, _extend.extend)({}, item, {
                                    children: null,
                                    type: "T",
                                    expanded: showTotalsPrior ? true : null,
                                    isAdditionalTotal: true
                                }));
                                if (showTotalsPrior) {
                                    item.expanded = null
                                }
                            }
                        }))
                    }(viewHeaderItems, headerDescriptions, options.showTotalsPrior, "tree" === options.layout)
                }(0, _deferred.when)((0, _m_widget_utils.foreachTreeAsync)(viewHeaderItems, (items => {
                    const item = items[0];
                    if (!item.children || 0 === item.children.length) {
                        item.depthSize = depthSize - items.length + 1
                    }
                }))).done((() => {
                    if (cellDescriptionsCount > 1) {
                        ! function(headerItems, cellDescriptions, options) {
                            (0, _m_widget_utils.foreachTree)(headerItems, (items => {
                                const item = items[0];
                                let i;
                                if (!item.children || 0 === item.children.length) {
                                    item.children = [];
                                    for (i = 0; i < cellDescriptions.length; i += 1) {
                                        const isGrandTotal = "GT" === item.type;
                                        const isTotal = "T" === item.type;
                                        const isValue = "D" === item.type;
                                        const columnIsHidden = false === cellDescriptions[i].visible || isGrandTotal && options.hiddenGrandTotals.includes(i) || isTotal && options.hiddenTotals.includes(i) || isValue && options.hiddenValues.includes(i);
                                        if (columnIsHidden) {
                                            continue
                                        }
                                        item.children.push({
                                            caption: cellDescriptions[i].caption,
                                            path: item.path,
                                            type: item.type,
                                            value: i,
                                            index: item.index,
                                            dataIndex: i,
                                            isMetric: true,
                                            isEmpty: item.isEmpty && item.isEmpty[i]
                                        })
                                    }
                                }
                            }))
                        }(viewHeaderItems, cellDescriptions, options)
                    }!options.showEmpty && function(headerItems) {
                        (0, _m_widget_utils.foreachTree)([{
                            children: headerItems
                        }], ((items, index) => {
                            const item = items[0];
                            const parentChildren = (items[1] ? items[1].children : headerItems) || [];
                            let {
                                isEmpty: isEmpty
                            } = item;
                            if (isEmpty && isEmpty.length) {
                                isEmpty = item.isEmpty.filter((isEmpty => isEmpty)).length === isEmpty.length
                            }
                            if (item && !item.children && isEmpty) {
                                parentChildren.splice(index, 1);
                                removeEmptyParent(items, 1)
                            }
                        }))
                    }(viewHeaderItems);
                    options.notifyProgress(.75);
                    (0, _deferred.when)((0, _m_widget_utils.foreachTreeAsync)(viewHeaderItems, (items => {
                        const item = items[0];
                        const {
                            isMetric: isMetric
                        } = item;
                        const field = headerDescriptions[items.length - 1] || {};
                        if ("D" === item.type && !isMetric) {
                            item.width = field.width
                        }
                        if (hideData && "D" === item.type) {
                            const parentChildren = (items[1] ? items[1].children : viewHeaderItems) || [];
                            parentChildren.splice(parentChildren.indexOf(item), 1);
                            return
                        }
                        if (isMetric) {
                            item.wordWrapEnabled = cellDescriptions[item.dataIndex].wordWrapEnabled
                        } else {
                            item.wordWrapEnabled = field.wordWrapEnabled
                        }
                        item.isLast = !item.children || !item.children.length;
                        if (item.isLast) {
                            (0, _iterator.each)(options.sortBySummaryPaths, ((_, sortBySummaryPath) => {
                                if (!(0, _type.isDefined)(item.dataIndex)) {
                                    sortBySummaryPath = sortBySummaryPath.slice(0);
                                    sortBySummaryPath.pop()
                                }
                                if (function(items, sortBySummaryPath) {
                                        let path;
                                        const item = items[0];
                                        const stringValuesUsed = (0, _type.isString)(sortBySummaryPath[0]);
                                        const headerItem = item.dataIndex >= 0 ? items[1] : item;
                                        if (stringValuesUsed && -1 !== sortBySummaryPath[0].indexOf("&[") && headerItem.key || !headerItem.key) {
                                            path = (0, _m_widget_utils.createPath)(items)
                                        } else {
                                            path = (0, _iterator.map)(items, (item => item.dataIndex >= 0 ? item.value : item.text)).reverse()
                                        }
                                        if ("GT" === item.type) {
                                            path = path.slice(1)
                                        }
                                        return path.join("/") === sortBySummaryPath.join("/")
                                    }(items, sortBySummaryPath)) {
                                    item.sorted = true;
                                    return false
                                }
                                return
                            }))
                        }
                        item.text = function(item, description, options) {
                            let {
                                text: text
                            } = item;
                            if ((0, _type.isDefined)(item.displayText)) {
                                text = item.displayText
                            } else if ((0, _type.isDefined)(item.caption)) {
                                text = item.caption
                            } else if ("GT" === item.type) {
                                text = options.texts.grandTotal
                            }
                            if (item.isAdditionalTotal) {
                                text = (0, _string.format)(options.texts.total || "", text)
                            }
                            return text
                        }(item, 0, options)
                    }))).done((() => {
                        if (!viewHeaderItems.length) {
                            viewHeaderItems.push({})
                        }
                        options.notifyProgress(1);
                        d.resolve(viewHeaderItems)
                    }))
                }))
            }));
            return d
        };

        function createHeaderItem(childrenStack, depth, index) {
            const parent = childrenStack[depth] = childrenStack[depth] || [];
            const node = parent[index] = {};
            if (childrenStack[depth + 1]) {
                node.children = childrenStack[depth + 1];
                for (let i = depth + 1; i < childrenStack.length; i += 1) {
                    childrenStack[i] = void 0
                }
                childrenStack.length = depth + 1
            }
            return node
        }
        const removeEmptyParent = function(items, index) {
            const parent = items[index + 1];
            if (!items[index].children.length && parent && parent.children) {
                parent.children.splice(parent.children.indexOf(items[index]), 1);
                removeEmptyParent(items, index + 1)
            }
        };
        return function(headerItems, headerDescriptions, cellDescriptions, isHorizontal, options) {
            const info = [];
            const depthSize = function(headerItems) {
                let depth = 0;
                (0, _m_widget_utils.foreachTree)(headerItems, (items => {
                    depth = math.max(depth, items.length)
                }));
                return depth
            }(headerItems) || 1;
            const d = new _deferred.Deferred;
            getViewHeaderItems(headerItems, headerDescriptions, cellDescriptions, depthSize, options).done((viewHeaderItems => {
                ! function(info, viewHeaderItems, depthSize, isHorizontal, isTree) {
                    let lastIndex = 0;
                    let index;
                    let depth;
                    const indexesByDepth = [0];
                    (0, _m_widget_utils.foreachTree)(viewHeaderItems, (items => {
                        const headerItem = items[0];
                        depth = headerItem.isMetric ? depthSize : items.length - 1;
                        while (indexesByDepth.length - 1 < depth) {
                            indexesByDepth.push(indexesByDepth[indexesByDepth.length - 1])
                        }
                        index = indexesByDepth[depth] || 0;
                        lastIndex = addInfoItem(info, {
                            headerItem: headerItem,
                            index: index,
                            lastIndex: lastIndex,
                            depth: depth,
                            isHorizontal: isHorizontal,
                            isTree: isTree
                        });
                        indexesByDepth.length = depth;
                        indexesByDepth.push(lastIndex)
                    }))
                }(info, viewHeaderItems, depthSize, isHorizontal, "tree" === options.layout);
                options.notifyProgress(1);
                d.resolve(info)
            }));
            return d
        }
    }();

    function createSortPaths(headerFields, dataFields) {
        const sortBySummaryPaths = [];
        (0, _iterator.each)(headerFields, ((_, headerField) => {
            const fieldIndex = (0, _m_widget_utils.findField)(dataFields, headerField.sortBySummaryField);
            if (fieldIndex >= 0) {
                sortBySummaryPaths.push((headerField.sortBySummaryPath || []).concat([fieldIndex]))
            }
        }));
        return sortBySummaryPaths
    }

    function foreachRowInfo(rowsInfo, callback) {
        let columnOffset = 0;
        const columnOffsetResetIndexes = [];
        for (let i = 0; i < rowsInfo.length; i += 1) {
            for (let j = 0; j < rowsInfo[i].length; j += 1) {
                const rowSpanOffset = (rowsInfo[i][j].rowspan || 1) - 1;
                const visibleIndex = i + rowSpanOffset;
                if (columnOffsetResetIndexes[i]) {
                    columnOffset -= columnOffsetResetIndexes[i];
                    columnOffsetResetIndexes[i] = 0
                }
                if (false === callback(rowsInfo[i][j], visibleIndex, i, j, columnOffset)) {
                    break
                }
                columnOffsetResetIndexes[i + (rowsInfo[i][j].rowspan || 1)] = (columnOffsetResetIndexes[i + (rowsInfo[i][j].rowspan || 1)] || 0) + 1;
                columnOffset += 1
            }
        }
    }

    function getHeaderIndexedItems(headerItems, options) {
        let visibleIndex = 0;
        const indexedItems = [];
        (0, _m_widget_utils.foreachTree)(headerItems, (items => {
            const headerItem = items[0];
            const path = (0, _m_widget_utils.createPath)(items);
            if (headerItem.children && false === options.showTotals) {
                return
            }
            const indexedItem = (0, _extend.extend)(true, {}, headerItem, {
                visibleIndex: visibleIndex += 1,
                path: path
            });
            if ((0, _type.isDefined)(indexedItem.index)) {
                indexedItems[indexedItem.index] = indexedItem
            } else {
                indexedItems.push(indexedItem)
            }
        }));
        return indexedItems
    }

    function createScrollController(dataController, component, dataAdapter) {
        return new _m_virtual_scrolling_core.default.VirtualScrollController(component, (0, _extend.extend)({
            hasKnownLastPage: () => true,
            pageCount() {
                return math.ceil(this.totalItemsCount() / this.pageSize())
            },
            updateLoading() {},
            itemsCount() {
                if (this.pageIndex() < this.pageCount() - 1) {
                    return this.pageSize()
                }
                return this.totalItemsCount() % this.pageSize()
            },
            items: () => [],
            viewportItems: () => [],
            onChanged() {},
            isLoading: () => dataController.isLoading(),
            changingDuration() {
                const dataSource = dataController._dataSource;
                if (dataSource.paginate()) {
                    return 300
                }
                return dataController._changingDuration || 0
            }
        }, dataAdapter))
    }
    const members = {
        ctor(options) {
            const that = this;
            const virtualScrollControllerChanged = that._fireChanged.bind(that);
            options = that._options = options || {};
            that.dataSourceChanged = (0, _callbacks.default)();
            that._dataSource = that._createDataSource(options);
            if (options.component && "virtual" === options.component.option("scrolling.mode")) {
                that._rowsScrollController = createScrollController(that, options.component, {
                    totalItemsCount: () => that.totalRowCount(),
                    pageIndex: index => that.rowPageIndex(index),
                    pageSize: () => that.rowPageSize(),
                    load() {
                        if (that._rowsScrollController.pageIndex() >= this.pageCount()) {
                            that._rowsScrollController.pageIndex(this.pageCount() - 1)
                        }
                        return that._rowsScrollController.handleDataChanged((function() {
                            if (that._dataSource.paginate()) {
                                that._dataSource.load()
                            } else {
                                virtualScrollControllerChanged.apply(this, arguments)
                            }
                        }))
                    }
                });
                that._columnsScrollController = createScrollController(that, options.component, {
                    totalItemsCount: () => that.totalColumnCount(),
                    pageIndex: index => that.columnPageIndex(index),
                    pageSize: () => that.columnPageSize(),
                    load() {
                        if (that._columnsScrollController.pageIndex() >= this.pageCount()) {
                            that._columnsScrollController.pageIndex(this.pageCount() - 1)
                        }
                        return that._columnsScrollController.handleDataChanged((function() {
                            if (that._dataSource.paginate()) {
                                that._dataSource.load()
                            } else {
                                virtualScrollControllerChanged.apply(this, arguments)
                            }
                        }))
                    }
                })
            }
            that._stateStoringController = new _m_state_storing_core.default.StateStoringController(options.component).init();
            that._columnsInfo = [];
            that._rowsInfo = [];
            that._cellsInfo = [];
            that.expandValueChanging = (0, _callbacks.default)();
            that.loadingChanged = (0, _callbacks.default)();
            that.progressChanged = (0, _callbacks.default)();
            that.scrollChanged = (0, _callbacks.default)();
            that.load();
            that._update();
            that.changed = (0, _callbacks.default)()
        },
        _fireChanged() {
            const startChanging = new Date;
            this.changed && !this._lockChanged && this.changed.fire();
            this._changingDuration = new Date - startChanging
        },
        _correctSkipsTakes(rowIndex, rowSkip, rowSpan, levels, skips, takes) {
            const endIndex = rowSpan ? rowIndex + rowSpan - 1 : rowIndex;
            skips[levels.length] = skips[levels.length] || 0;
            takes[levels.length] = takes[levels.length] || 0;
            if (endIndex < rowSkip) {
                skips[levels.length] += 1
            } else {
                takes[levels.length] += 1
            }
        },
        _calculatePagingForRowExpandedPaths(options, skips, takes, rowExpandedSkips, rowExpandedTakes) {
            const rows = this._rowsInfo;
            const rowCount = Math.min(options.rowSkip + options.rowTake, rows.length);
            const {
                rowExpandedPaths: rowExpandedPaths
            } = options;
            let levels = [];
            const expandedPathIndexes = {};
            let i;
            let j;
            let path;
            rowExpandedPaths.forEach(((path, index) => {
                expandedPathIndexes[path] = index
            }));
            for (i = 0; i < rowCount; i += 1) {
                takes.length = skips.length = levels.length + 1;
                for (j = 0; j < rows[i].length; j += 1) {
                    const cell = rows[i][j];
                    if ("D" === cell.type) {
                        this._correctSkipsTakes(i, options.rowSkip, cell.rowspan, levels, skips, takes);
                        path = cell.path || path;
                        const expandIndex = path && path.length > 1 ? expandedPathIndexes[path.slice(0, -1)] : -1;
                        if (expandIndex >= 0) {
                            rowExpandedSkips[expandIndex] = skips[levels.length] || 0;
                            rowExpandedTakes[expandIndex] = takes[levels.length] || 0
                        }
                        if (cell.rowspan) {
                            levels.push(cell.rowspan)
                        }
                    }
                }
                levels = levels.map((level => level - 1)).filter((level => level > 0))
            }
        },
        _calculatePagingForColumnExpandedPaths(options, skips, takes, expandedSkips, expandedTakes) {
            const skipByPath = {};
            const takeByPath = {};
            (0, _m_virtual_columns_core.foreachColumnInfo)(this._columnsInfo, ((columnInfo, columnIndex) => {
                if ("D" === columnInfo.type && columnInfo.path && void 0 === columnInfo.dataIndex) {
                    const colspan = columnInfo.colspan || 1;
                    const path = columnInfo.path.slice(0, -1).toString();
                    skipByPath[path] = skipByPath[path] || 0;
                    takeByPath[path] = takeByPath[path] || 0;
                    if (columnIndex + colspan <= options.columnSkip) {
                        skipByPath[path] += 1
                    } else if (columnIndex < options.columnSkip + options.columnTake) {
                        takeByPath[path] += 1
                    }
                }
            }));
            skips[0] = skipByPath[""];
            takes[0] = takeByPath[""];
            options.columnExpandedPaths.forEach(((path, index) => {
                const skip = skipByPath[path];
                const take = takeByPath[path];
                if (void 0 !== skip) {
                    expandedSkips[index] = skip
                }
                if (void 0 !== take) {
                    expandedTakes[index] = take
                }
            }))
        },
        _processPagingForExpandedPaths(options, area, storeLoadOptions, reload) {
            const expandedPaths = options[`${area}ExpandedPaths`];
            const expandedSkips = expandedPaths.map((() => 0));
            const expandedTakes = expandedPaths.map((() => reload ? options.pageSize : 0));
            const skips = [];
            const takes = [];
            if (!reload) {
                if ("row" === area) {
                    this._calculatePagingForRowExpandedPaths(options, skips, takes, expandedSkips, expandedTakes)
                } else {
                    this._calculatePagingForColumnExpandedPaths(options, skips, takes, expandedSkips, expandedTakes)
                }
            }
            this._savePagingForExpandedPaths(options, area, storeLoadOptions, skips[0], takes[0], expandedSkips, expandedTakes)
        },
        _savePagingForExpandedPaths(options, area, storeLoadOptions, skip, take, expandedSkips, expandedTakes) {
            const expandedPaths = options[`${area}ExpandedPaths`];
            options[`${area}ExpandedPaths`] = [];
            options[`${area}Skip`] = void 0 !== skip ? skip : options[`${area}Skip`];
            options[`${area}Take`] = void 0 !== take ? take : options[`${area}Take`];
            for (let i = 0; i < expandedPaths.length; i += 1) {
                if (expandedTakes[i]) {
                    const isOppositeArea = options.area && options.area !== area;
                    storeLoadOptions.push((0, _extend.extend)({
                        area: area,
                        headerName: `${area}s`
                    }, options, {
                        [`${area}Skip`]: expandedSkips[i],
                        [`${area}Take`]: expandedTakes[i],
                        [isOppositeArea ? "oppositePath" : "path"]: expandedPaths[i]
                    }))
                }
            }
        },
        _handleCustomizeStoreLoadOptions(storeLoadOptions, reload) {
            const options = storeLoadOptions[0];
            const rowsScrollController = this._rowsScrollController;
            if (this._dataSource.paginate() && rowsScrollController) {
                const rowPageSize = rowsScrollController.pageSize();
                if ("rows" === options.headerName) {
                    options.rowSkip = 0;
                    options.rowTake = rowPageSize;
                    options.rowExpandedPaths = []
                } else {
                    options.rowSkip = rowsScrollController.beginPageIndex() * rowPageSize;
                    options.rowTake = (rowsScrollController.endPageIndex() - rowsScrollController.beginPageIndex() + 1) * rowPageSize;
                    this._processPagingForExpandedPaths(options, "row", storeLoadOptions, reload)
                }
            }
            const columnsScrollController = this._columnsScrollController;
            if (this._dataSource.paginate() && columnsScrollController) {
                const columnPageSize = columnsScrollController.pageSize();
                storeLoadOptions.forEach((options => {
                    if ("columns" === options.headerName) {
                        options.columnSkip = 0;
                        options.columnTake = columnPageSize;
                        options.columnExpandedPaths = []
                    } else {
                        options.columnSkip = columnsScrollController.beginPageIndex() * columnPageSize;
                        options.columnTake = (columnsScrollController.endPageIndex() - columnsScrollController.beginPageIndex() + 1) * columnPageSize;
                        this._processPagingForExpandedPaths(options, "column", storeLoadOptions, reload)
                    }
                }))
            }
        },
        load() {
            const that = this;
            const stateStoringController = this._stateStoringController;
            if (stateStoringController.isEnabled() && !stateStoringController.isLoaded()) {
                stateStoringController.load().always((state => {
                    if (state) {
                        that._dataSource.state(state)
                    } else {
                        that._dataSource.load()
                    }
                }))
            } else {
                that._dataSource.load()
            }
        },
        calculateVirtualContentParams(contentParams) {
            const that = this;
            const rowsScrollController = that._rowsScrollController;
            const columnsScrollController = that._columnsScrollController;
            if (rowsScrollController && columnsScrollController) {
                rowsScrollController.viewportItemSize(contentParams.virtualRowHeight);
                rowsScrollController.viewportSize(contentParams.viewportHeight / rowsScrollController.viewportItemSize());
                rowsScrollController.setContentItemSizes(contentParams.itemHeights);
                columnsScrollController.viewportItemSize(contentParams.virtualColumnWidth);
                columnsScrollController.viewportSize(contentParams.viewportWidth / columnsScrollController.viewportItemSize());
                columnsScrollController.setContentItemSizes(contentParams.itemWidths);
                (0, _common.deferUpdate)((() => {
                    columnsScrollController.loadIfNeed();
                    rowsScrollController.loadIfNeed()
                }));
                that.scrollChanged.fire({
                    left: columnsScrollController.getViewportPosition(),
                    top: rowsScrollController.getViewportPosition()
                });
                return {
                    contentTop: rowsScrollController.getContentOffset(),
                    contentLeft: columnsScrollController.getContentOffset(),
                    width: columnsScrollController.getVirtualContentSize(),
                    height: rowsScrollController.getVirtualContentSize()
                }
            }
            return
        },
        setViewportPosition(left, top) {
            this._rowsScrollController.setViewportPosition(top || 0);
            this._columnsScrollController.setViewportPosition(left || 0)
        },
        subscribeToWindowScrollEvents($element) {
            var _this$_rowsScrollCont;
            null === (_this$_rowsScrollCont = this._rowsScrollController) || void 0 === _this$_rowsScrollCont || _this$_rowsScrollCont.subscribeToWindowScrollEvents($element)
        },
        updateWindowScrollPosition(position) {
            var _this$_rowsScrollCont2;
            null === (_this$_rowsScrollCont2 = this._rowsScrollController) || void 0 === _this$_rowsScrollCont2 || _this$_rowsScrollCont2.scrollTo(position)
        },
        updateViewOptions(options) {
            (0, _extend.extend)(this._options, options);
            this._update()
        },
        _handleExpandValueChanging(e) {
            this.expandValueChanging.fire(e)
        },
        _handleLoadingChanged(isLoading) {
            this.loadingChanged.fire(isLoading)
        },
        _handleProgressChanged(progress) {
            this.progressChanged.fire(progress)
        },
        _handleFieldsPrepared(e) {
            this._options.onFieldsPrepared && this._options.onFieldsPrepared(e)
        },
        _createDataSource(options) {
            const that = this;
            const dataSourceOptions = options.dataSource;
            let dataSource;
            that._isSharedDataSource = dataSourceOptions instanceof _m_data_source.PivotGridDataSource;
            if (that._isSharedDataSource) {
                dataSource = dataSourceOptions
            } else {
                dataSource = new _m_data_source.PivotGridDataSource(dataSourceOptions)
            }
            that._expandValueChangingHandler = that._handleExpandValueChanging.bind(that);
            that._loadingChangedHandler = that._handleLoadingChanged.bind(that);
            that._fieldsPreparedHandler = that._handleFieldsPrepared.bind(that);
            that._customizeStoreLoadOptionsHandler = that._handleCustomizeStoreLoadOptions.bind(that);
            that._changedHandler = function() {
                that._update();
                that.dataSourceChanged.fire()
            };
            that._progressChangedHandler = function(progress) {
                that._handleProgressChanged(.8 * progress)
            };
            dataSource.on("changed", that._changedHandler);
            dataSource.on("expandValueChanging", that._expandValueChangingHandler);
            dataSource.on("loadingChanged", that._loadingChangedHandler);
            dataSource.on("progressChanged", that._progressChangedHandler);
            dataSource.on("fieldsPrepared", that._fieldsPreparedHandler);
            dataSource.on("customizeStoreLoadOptions", that._customizeStoreLoadOptionsHandler);
            return dataSource
        },
        getDataSource() {
            return this._dataSource
        },
        isLoading() {
            return this._dataSource.isLoading()
        },
        beginLoading() {
            this._dataSource.beginLoading()
        },
        endLoading() {
            this._dataSource.endLoading()
        },
        _update() {
            const that = this;
            const dataSource = that._dataSource;
            const options = that._options;
            const columnFields = dataSource.getAreaFields("column");
            const rowFields = dataSource.getAreaFields("row");
            const dataFields = dataSource.getAreaFields("data");
            const dataFieldsForRows = "row" === options.dataFieldArea ? dataFields : [];
            const dataFieldsForColumns = "row" !== options.dataFieldArea ? dataFields : [];
            const data = dataSource.getData();
            const hiddenTotals = function(dataFields) {
                const result = [];
                (0, _iterator.each)(dataFields, ((index, field) => {
                    if (false === field.showTotals) {
                        result.push(index)
                    }
                }));
                return result
            }(dataFields);
            const hiddenValues = function(dataFields) {
                const result = [];
                dataFields.forEach(((field, index) => {
                    if (void 0 === field.showValues && false === field.showTotals || false === field.showValues) {
                        result.push(index)
                    }
                }));
                return result
            }(dataFields);
            const hiddenGrandTotals = function(dataFields, columnFields) {
                let result = [];
                (0, _iterator.each)(dataFields, ((index, field) => {
                    if (false === field.showGrandTotals) {
                        result.push(index)
                    }
                }));
                if (0 === columnFields.length && result.length === dataFields.length) {
                    result = []
                }
                return result
            }(dataFields, columnFields);
            const grandTotalsAreHiddenForNotAllDataFields = dataFields.length > 0 ? hiddenGrandTotals.length !== dataFields.length : true;
            const rowOptions = {
                isEmptyGrandTotal: data.isEmptyGrandTotalRow,
                texts: options.texts || {},
                hiddenTotals: hiddenTotals,
                hiddenValues: hiddenValues,
                hiddenGrandTotals: [],
                showTotals: options.showRowTotals,
                showGrandTotals: false !== options.showRowGrandTotals && grandTotalsAreHiddenForNotAllDataFields,
                sortBySummaryPaths: createSortPaths(columnFields, dataFields),
                showTotalsPrior: "rows" === options.showTotalsPrior || "both" === options.showTotalsPrior,
                showEmpty: !options.hideEmptySummaryCells,
                layout: options.rowHeaderLayout,
                fields: rowFields,
                dataFields: dataFields,
                progress: 0
            };
            const columnOptions = {
                isEmptyGrandTotal: data.isEmptyGrandTotalColumn,
                texts: options.texts || {},
                hiddenTotals: hiddenTotals,
                hiddenValues: hiddenValues,
                hiddenGrandTotals: hiddenGrandTotals,
                showTotals: options.showColumnTotals,
                showTotalsPrior: "columns" === options.showTotalsPrior || "both" === options.showTotalsPrior,
                showGrandTotals: false !== options.showColumnGrandTotals && grandTotalsAreHiddenForNotAllDataFields,
                sortBySummaryPaths: createSortPaths(rowFields, dataFields),
                showEmpty: !options.hideEmptySummaryCells,
                fields: columnFields,
                dataFields: dataFields,
                progress: 0
            };
            const notifyProgress = function(progress) {
                this.progress = progress;
                that._handleProgressChanged(.8 + .1 * rowOptions.progress + .1 * columnOptions.progress)
            };
            rowOptions.notifyProgress = notifyProgress;
            columnOptions.notifyProgress = notifyProgress;
            if (!(0, _type.isDefined)(data.grandTotalRowIndex)) {
                data.grandTotalRowIndex = getHeaderIndexedItems(data.rows, rowOptions).length
            }
            if (!(0, _type.isDefined)(data.grandTotalColumnIndex)) {
                data.grandTotalColumnIndex = getHeaderIndexedItems(data.columns, columnOptions).length
            }
            dataSource._changeLoadingCount(1);
            (0, _deferred.when)(createHeaderInfo(data.columns, columnFields, dataFieldsForColumns, true, columnOptions), createHeaderInfo(data.rows, rowFields, dataFieldsForRows, false, rowOptions)).always((() => {
                dataSource._changeLoadingCount(-1)
            })).done(((columnsInfo, rowsInfo) => {
                that._columnsInfo = columnsInfo;
                that._rowsInfo = rowsInfo;
                if (that._rowsScrollController && that._columnsScrollController && that.changed && !that._dataSource.paginate()) {
                    that._rowsScrollController.reset(true);
                    that._columnsScrollController.reset(true);
                    that._lockChanged = true;
                    that._rowsScrollController.load();
                    that._columnsScrollController.load();
                    that._lockChanged = false
                }
            })).done((() => {
                that._fireChanged();
                if (that._stateStoringController.isEnabled() && !that._dataSource.isLoading()) {
                    that._stateStoringController.state(that._dataSource.state());
                    that._stateStoringController.save()
                }
            }))
        },
        getRowsInfo(getAllData) {
            const that = this;
            const rowsInfo = that._rowsInfo;
            const scrollController = that._rowsScrollController;
            let rowspan;
            if (scrollController && !getAllData) {
                const startIndex = scrollController.beginPageIndex() * that.rowPageSize();
                const endIndex = scrollController.endPageIndex() * that.rowPageSize() + that.rowPageSize();
                const summaryFields = that._dataSource.getSummaryFields();
                const isRowDataFieldArea = "row" === this._options.dataFieldArea;
                const newRowsInfo = [];
                let maxDepth = 1;
                foreachRowInfo(rowsInfo, ((rowInfo, visibleIndex, rowIndex, _, columnIndex) => {
                    const isVisible = visibleIndex >= startIndex && rowIndex < endIndex;
                    const index = rowIndex < startIndex ? 0 : rowIndex - startIndex;
                    let cell = rowInfo;
                    if (isVisible) {
                        newRowsInfo[index] = newRowsInfo[index] || [];
                        rowspan = rowIndex < startIndex ? rowInfo.rowspan - (startIndex - rowIndex) || 1 : rowInfo.rowspan;
                        if (startIndex + index + rowspan > endIndex) {
                            rowspan = endIndex - (index + startIndex) || 1
                        }
                        if (rowspan !== rowInfo.rowspan) {
                            cell = (0, _extend.extend)({}, cell, {
                                rowspan: rowspan
                            })
                        }
                        newRowsInfo[index].push(cell);
                        const isSummaryCell = summaryFields.some((field => field.caption === cell.text));
                        if (!isRowDataFieldArea || !isSummaryCell) {
                            maxDepth = math.max(maxDepth, columnIndex + 1)
                        }
                    } else {
                        return false
                    }
                    return
                }));
                foreachRowInfo(newRowsInfo, ((rowInfo, visibleIndex, rowIndex, columnIndex, realColumnIndex) => {
                    const colspan = rowInfo.colspan || 1;
                    if (realColumnIndex + colspan > maxDepth) {
                        newRowsInfo[rowIndex][columnIndex] = (0, _extend.extend)({}, rowInfo, {
                            colspan: maxDepth - realColumnIndex || 1
                        })
                    }
                }));
                return newRowsInfo
            }
            return rowsInfo
        },
        getColumnsInfo(getAllData) {
            const that = this;
            let info = that._columnsInfo;
            const scrollController = that._columnsScrollController;
            if (scrollController && !getAllData) {
                const startIndex = scrollController.beginPageIndex() * that.columnPageSize();
                const endIndex = scrollController.endPageIndex() * that.columnPageSize() + that.columnPageSize();
                info = (0, _m_virtual_columns_core.createColumnsInfo)(info, startIndex, endIndex)
            }
            return info
        },
        totalRowCount() {
            return this._rowsInfo.length
        },
        rowPageIndex(index) {
            if (void 0 !== index) {
                this._rowPageIndex = index
            }
            return this._rowPageIndex || 0
        },
        totalColumnCount() {
            let count = 0;
            if (this._columnsInfo && this._columnsInfo.length) {
                for (let i = 0; i < this._columnsInfo[0].length; i += 1) {
                    count += this._columnsInfo[0][i].colspan || 1
                }
            }
            return count
        },
        rowPageSize(size) {
            if (void 0 !== size) {
                this._rowPageSize = size
            }
            return this._rowPageSize || 20
        },
        columnPageSize(size) {
            if (void 0 !== size) {
                this._columnPageSize = size
            }
            return this._columnPageSize || 20
        },
        columnPageIndex(index) {
            if (void 0 !== index) {
                this._columnPageIndex = index
            }
            return this._columnPageIndex || 0
        },
        getCellsInfo(getAllData) {
            const rowsInfo = this.getRowsInfo(getAllData);
            const columnsInfo = this.getColumnsInfo(getAllData);
            const data = this._dataSource.getData();
            const texts = this._options.texts || {};
            return function(rowsInfo, columnsInfo, data, dataFields, dataFieldArea, errorText) {
                const info = [];
                const dataFieldAreaInRows = "row" === dataFieldArea;
                const dataSourceCells = data.values;
                dataSourceCells.length && foreachRowInfo(rowsInfo, ((rowInfo, rowIndex) => {
                    const row = info[rowIndex] = [];
                    const dataRow = dataSourceCells[rowInfo.dataSourceIndex >= 0 ? rowInfo.dataSourceIndex : data.grandTotalRowIndex] || [];
                    rowInfo.isLast && (0, _m_virtual_columns_core.foreachColumnInfo)(columnsInfo, ((columnInfo, columnIndex) => {
                        const dataIndex = (dataFieldAreaInRows ? rowInfo.dataIndex : columnInfo.dataIndex) || 0;
                        const dataField = dataFields[dataIndex];
                        if (columnInfo.isLast && dataField && false !== dataField.visible) {
                            let cell = dataRow[columnInfo.dataSourceIndex >= 0 ? columnInfo.dataSourceIndex : data.grandTotalColumnIndex];
                            if (!Array.isArray(cell)) {
                                cell = [cell]
                            }
                            const cellValue = cell[dataIndex];
                            row[columnIndex] = {
                                text: formatCellValue(cellValue, dataField, errorText),
                                value: cellValue,
                                format: dataField.format,
                                dataType: dataField.dataType,
                                columnType: columnInfo.type,
                                rowType: rowInfo.type,
                                rowPath: rowInfo.path || [],
                                columnPath: columnInfo.path || [],
                                dataIndex: dataIndex
                            };
                            if (dataField.width) {
                                row[columnIndex].width = dataField.width
                            }
                        }
                    }))
                }));
                return info
            }(rowsInfo, columnsInfo, data, this._dataSource.getAreaFields("data"), this._options.dataFieldArea, texts.dataNotAvailable)
        },
        dispose() {
            const that = this;
            if (that._isSharedDataSource) {
                that._dataSource.off("changed", that._changedHandler);
                that._dataSource.off("expandValueChanging", that._expandValueChangingHandler);
                that._dataSource.off("loadingChanged", that._loadingChangedHandler);
                that._dataSource.off("progressChanged", that._progressChangedHandler);
                that._dataSource.off("fieldsPrepared", that._fieldsPreparedHandler);
                that._dataSource.off("customizeStoreLoadOptions", that._customizeStoreLoadOptionsHandler)
            } else {
                that._dataSource.dispose()
            }
            that._columnsScrollController && that._columnsScrollController.dispose();
            that._rowsScrollController && that._rowsScrollController.dispose();
            that._stateStoringController.dispose();
            that.expandValueChanging.empty();
            that.changed.empty();
            that.loadingChanged.empty();
            that.progressChanged.empty();
            that.scrollChanged.empty();
            that.dataSourceChanged.empty()
        }
    };
    proxyMethod(members, "applyPartialDataSource");
    proxyMethod(members, "collapseHeaderItem");
    proxyMethod(members, "expandHeaderItem");
    proxyMethod(members, "getData");
    proxyMethod(members, "isEmpty");
    return members
}());
const DataController__internals = exports.DataController__internals = {
    NO_DATA_AVAILABLE_TEXT: "#N/A"
};
var _default = exports.default = {
    DataController: DataController,
    DataController__internals: DataController__internals
};
