"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSortedRowModel = getSortedRowModel;
const utils_1 = require("../utils");
function getSortedRowModel() {
    return (table) => (0, utils_1.memo)(() => [table.getState().sorting, table.getPreSortedRowModel()], (sorting, rowModel) => {
        if (!rowModel.rows.length || !(sorting === null || sorting === void 0 ? void 0 : sorting.length)) {
            return rowModel;
        }
        const sortingState = table.getState().sorting;
        const sortedFlatRows = [];
        // Filter out sortings that correspond to non existing columns
        const availableSorting = sortingState.filter((sort) => { var _a; return (_a = table.getColumn(sort.id)) === null || _a === void 0 ? void 0 : _a.getCanSort(); });
        const columnInfoById = {};
        availableSorting.forEach((sortEntry) => {
            const column = table.getColumn(sortEntry.id);
            if (!column)
                return;
            columnInfoById[sortEntry.id] = {
                sortUndefined: column.columnDef.sortUndefined,
                invertSorting: column.columnDef.invertSorting,
                sortingFn: column.getSortingFn(),
            };
        });
        const sortData = (rows) => {
            // This will also perform a stable sorting using the row index
            // if needed.
            const sortedData = rows.map((row) => ({ ...row }));
            sortedData.sort((rowA, rowB) => {
                var _a;
                for (let i = 0; i < availableSorting.length; i += 1) {
                    const sortEntry = availableSorting[i];
                    const columnInfo = columnInfoById[sortEntry.id];
                    const { sortUndefined } = columnInfo;
                    const isDesc = (_a = sortEntry === null || sortEntry === void 0 ? void 0 : sortEntry.desc) !== null && _a !== void 0 ? _a : false;
                    let sortInt = 0;
                    // All sorting ints should always return in ascending order
                    if (sortUndefined) {
                        const aValue = rowA.getValue(sortEntry.id);
                        const bValue = rowB.getValue(sortEntry.id);
                        const aUndefined = aValue === undefined;
                        const bUndefined = bValue === undefined;
                        if (aUndefined || bUndefined) {
                            if (sortUndefined === 'first')
                                return aUndefined ? -1 : 1;
                            if (sortUndefined === 'last')
                                return aUndefined ? 1 : -1;
                            if (aUndefined && bUndefined)
                                sortInt = 0;
                            else if (aUndefined)
                                sortInt = sortUndefined;
                            else
                                sortInt = -sortUndefined;
                        }
                    }
                    if (sortInt === 0) {
                        sortInt = columnInfo.sortingFn(rowA, rowB, sortEntry.id);
                    }
                    // If sorting is non-zero, take care of desc and inversion
                    if (sortInt !== 0) {
                        if (isDesc) {
                            sortInt *= -1;
                        }
                        if (columnInfo.invertSorting) {
                            sortInt *= -1;
                        }
                        return sortInt;
                    }
                }
                return rowA.index - rowB.index;
            });
            // If there are sub-rows, sort them
            sortedData.forEach((row) => {
                var _a;
                sortedFlatRows.push(row);
                if ((_a = row.subRows) === null || _a === void 0 ? void 0 : _a.length) {
                    row.subRows = sortData(row.subRows);
                }
            });
            return sortedData;
        };
        return {
            rows: sortData(rowModel.rows),
            flatRows: sortedFlatRows,
            rowsById: rowModel.rowsById,
        };
    }, (0, utils_1.getMemoOptions)(table.options, 'debugTable', 'getSortedRowModel', () => table._autoResetPageIndex()));
}
