/**
 * DevExtreme (esm/__internal/grids/pivot_grid/data_source/m_data_source_utils.js)
 * Version: 23.2.6 (build 24140-0112)
 * Build date: Sun May 19 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
import {
    map
} from "../../../../core/utils/iterator";
import {
    isDefined
} from "../../../../core/utils/type";
import {
    createPath,
    findField,
    foreachDataLevel,
    foreachTree,
    getCompareFunction
} from "../m_widget_utils";

function sort(loadOptions, dataSource, getAscOrder) {
    sortDimension(dataSource, loadOptions, "rows", getAscOrder);
    sortDimension(dataSource, loadOptions, "columns", getAscOrder)
}

function sortDimension(dataSource, loadOptions, dimensionName, getAscOrder) {
    var fields = loadOptions[dimensionName] || [];
    var baseIndex = loadOptions.headerName === dimensionName ? loadOptions.path.length : 0;
    var sortingMethodByLevel = [];
    foreachDataLevel(dataSource[dimensionName], (item, index) => {
        var field = fields[index] || {};
        var sortingMethod = sortingMethodByLevel[index] = sortingMethodByLevel[index] || getSortingMethod(field, dataSource, loadOptions, dimensionName, getAscOrder);
        item.sort(sortingMethod)
    }, baseIndex)
}

function getSortingMethod(field, dataSource, loadOptions, dimensionName, getAscOrder) {
    var sortOrder = getAscOrder ? "asc" : field.sortOrder;
    var sortBy = getMemberForSortBy(field.sortBy, getAscOrder);
    var defaultCompare = field.sortingMethod ? function(a, b) {
        return field.sortingMethod(a, b)
    } : getCompareFunction(item => item[sortBy]);
    var summaryValueSelector = !getAscOrder && getFieldSummaryValueSelector(field, dataSource, loadOptions, dimensionName);
    var summaryCompare = summaryValueSelector && getCompareFunction(summaryValueSelector);
    return function(a, b) {
        var result = summaryCompare && summaryCompare(a, b) || defaultCompare(a, b);
        return "desc" === sortOrder ? -result : result
    }
}

function getFieldSummaryValueSelector(field, dataSource, loadOptions, dimensionName) {
    var {
        values: values
    } = dataSource;
    var sortBySummaryFieldIndex = findField(loadOptions.values, field.sortBySummaryField);
    var areRows = "rows" === dimensionName;
    var sortByDimension = areRows ? dataSource.columns : dataSource.rows;
    var grandTotalIndex = areRows ? dataSource.grandTotalRowIndex : dataSource.grandTotalColumnIndex;
    var sortBySummaryPath = field.sortBySummaryPath || [];
    var sliceIndex = sortBySummaryPath.length ? getSliceIndex(sortByDimension, sortBySummaryPath) : grandTotalIndex;
    if (values && values.length && sortBySummaryFieldIndex >= 0 && isDefined(sliceIndex)) {
        return function(field) {
            var rowIndex = areRows ? field.index : sliceIndex;
            var columnIndex = areRows ? sliceIndex : field.index;
            var value = ((values[rowIndex] || [
                []
            ])[columnIndex] || [])[sortBySummaryFieldIndex];
            return isDefined(value) ? value : null
        }
    }
    return
}

function getMemberForSortBy(sortBy, getAscOrder) {
    var member = "text";
    if ("none" === sortBy) {
        member = "index"
    } else if (getAscOrder || "displayText" !== sortBy) {
        member = "value"
    }
    return member
}

function getSliceIndex(items, path) {
    var index = null;
    var pathValue = (path || []).join(".");
    if (pathValue.length) {
        foreachTree(items, items => {
            var item = items[0];
            var itemPath = createPath(items).join(".");
            var textPath = map(items, item => item.text).reverse().join(".");
            if (pathValue === itemPath || item.key && textPath === pathValue) {
                index = items[0].index;
                return false
            }
            return
        })
    }
    return index
}
export default {
    sort: sort
};
export {
    sort
};
