"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RowSorting = void 0;
const sortingFns_1 = require("../sortingFns");
const utils_1 = require("../utils");
//
exports.RowSorting = {
    getInitialState: (state) => {
        return {
            sorting: [],
            ...state,
        };
    },
    getDefaultColumnDef: () => {
        return {
            sortingFn: 'auto',
            sortUndefined: 1,
        };
    },
    getDefaultOptions: (table) => {
        return {
            onSortingChange: (0, utils_1.makeStateUpdater)('sorting', table),
            isMultiSortEvent: (e) => {
                return e.shiftKey;
            },
        };
    },
    createColumn: (column, table) => {
        column.getAutoSortingFn = () => {
            const firstRows = table.getFilteredRowModel().flatRows.slice(10);
            let isString = false;
            for (const row of firstRows) {
                const value = row === null || row === void 0 ? void 0 : row.getValue(column.id);
                if (Object.prototype.toString.call(value) === '[object Date]') {
                    return sortingFns_1.sortingFns.datetime;
                }
                if (typeof value === 'string') {
                    isString = true;
                    if (value.split(sortingFns_1.reSplitAlphaNumeric).length > 1) {
                        return sortingFns_1.sortingFns.alphanumeric;
                    }
                }
            }
            if (isString) {
                return sortingFns_1.sortingFns.text;
            }
            return sortingFns_1.sortingFns.basic;
        };
        column.getAutoSortDir = () => {
            const firstRow = table.getFilteredRowModel().flatRows[0];
            const value = firstRow === null || firstRow === void 0 ? void 0 : firstRow.getValue(column.id);
            if (typeof value === 'string') {
                return 'asc';
            }
            return 'desc';
        };
        column.getSortingFn = () => {
            var _a, _b;
            if (!column) {
                throw new Error();
            }
            if ((0, utils_1.isFunction)(column.columnDef.sortingFn))
                return column.columnDef.sortingFn;
            if (column.columnDef.sortingFn === 'auto')
                return column.getAutoSortingFn();
            return ((_b = (_a = table.options.sortingFns) === null || _a === void 0 ? void 0 : _a[column.columnDef.sortingFn]) !== null && _b !== void 0 ? _b : sortingFns_1.sortingFns[column.columnDef.sortingFn]);
        };
        column.toggleSorting = (desc, multi) => {
            // if (column.columns.length) {
            //   column.columns.forEach((c, i) => {
            //     if (c.id) {
            //       table.toggleColumnSorting(c.id, undefined, multi || !!i)
            //     }
            //   })
            //   return
            // }
            // this needs to be outside of table.setSorting to be in sync with rerender
            const nextSortingOrder = column.getNextSortingOrder();
            const hasManualValue = typeof desc !== 'undefined' && desc !== null;
            table.setSorting((old) => {
                var _a;
                // Find any existing sorting for this column
                const existingSorting = old === null || old === void 0 ? void 0 : old.find((d) => d.id === column.id);
                const existingIndex = old === null || old === void 0 ? void 0 : old.findIndex((d) => d.id === column.id);
                let newSorting = [];
                // What should we do with this sort action?
                let sortAction;
                const nextDesc = hasManualValue ? desc : nextSortingOrder === 'desc';
                // Multi-mode
                if ((old === null || old === void 0 ? void 0 : old.length) && column.getCanMultiSort() && multi) {
                    if (existingSorting) {
                        sortAction = 'toggle';
                    }
                    else {
                        sortAction = 'add';
                    }
                }
                else if ((old === null || old === void 0 ? void 0 : old.length) && existingIndex !== old.length - 1) {
                    // Normal mode
                    sortAction = 'replace';
                }
                else if (existingSorting) {
                    sortAction = 'toggle';
                }
                else {
                    sortAction = 'replace';
                }
                // Handle toggle states that will remove the sorting
                if (sortAction === 'toggle') {
                    // If we are "actually" toggling (not a manual set value), should we remove the sorting?
                    if (!hasManualValue) {
                        // Is our intention to remove?
                        if (!nextSortingOrder) {
                            sortAction = 'remove';
                        }
                    }
                }
                if (sortAction === 'add') {
                    newSorting = [
                        ...old,
                        {
                            id: column.id,
                            desc: nextDesc,
                        },
                    ];
                    // Take latest n columns
                    newSorting.splice(0, newSorting.length - ((_a = table.options.maxMultiSortColCount) !== null && _a !== void 0 ? _a : Number.MAX_SAFE_INTEGER));
                }
                else if (sortAction === 'toggle') {
                    // This flips (or sets) the
                    newSorting = old.map((d) => {
                        if (d.id === column.id) {
                            return {
                                ...d,
                                desc: nextDesc,
                            };
                        }
                        return d;
                    });
                }
                else if (sortAction === 'remove') {
                    newSorting = old.filter((d) => d.id !== column.id);
                }
                else {
                    newSorting = [
                        {
                            id: column.id,
                            desc: nextDesc,
                        },
                    ];
                }
                return newSorting;
            });
        };
        column.getFirstSortDir = () => {
            var _a, _b;
            const sortDescFirst = (_b = (_a = column.columnDef.sortDescFirst) !== null && _a !== void 0 ? _a : table.options.sortDescFirst) !== null && _b !== void 0 ? _b : column.getAutoSortDir() === 'desc';
            return sortDescFirst ? 'desc' : 'asc';
        };
        column.getNextSortingOrder = (multi) => {
            var _a, _b;
            const firstSortDirection = column.getFirstSortDir();
            const isSorted = column.getIsSorted();
            if (!isSorted) {
                return firstSortDirection;
            }
            if (isSorted !== firstSortDirection &&
                ((_a = table.options.enableSortingRemoval) !== null && _a !== void 0 ? _a : true) && // If enableSortRemove, enable in general
                (multi ? ((_b = table.options.enableMultiRemove) !== null && _b !== void 0 ? _b : true) : true) // If multi, don't allow if enableMultiRemove))
            ) {
                return false;
            }
            return isSorted === 'desc' ? 'asc' : 'desc';
        };
        column.getCanSort = () => {
            var _a, _b;
            return (((_a = column.columnDef.enableSorting) !== null && _a !== void 0 ? _a : true) &&
                ((_b = table.options.enableSorting) !== null && _b !== void 0 ? _b : true) &&
                !!column.accessorFn);
        };
        column.getCanMultiSort = () => {
            var _a, _b;
            return ((_b = (_a = column.columnDef.enableMultiSort) !== null && _a !== void 0 ? _a : table.options.enableMultiSort) !== null && _b !== void 0 ? _b : !!column.accessorFn);
        };
        column.getIsSorted = () => {
            var _a;
            const columnSort = (_a = table.getState().sorting) === null || _a === void 0 ? void 0 : _a.find((d) => d.id === column.id);
            if (!columnSort)
                return false;
            return columnSort.desc ? 'desc' : 'asc';
        };
        column.getSortIndex = () => { var _a, _b; return (_b = (_a = table.getState().sorting) === null || _a === void 0 ? void 0 : _a.findIndex((d) => d.id === column.id)) !== null && _b !== void 0 ? _b : -1; };
        column.clearSorting = () => {
            // clear sorting for just 1 column
            table.setSorting((old) => ((old === null || old === void 0 ? void 0 : old.length) ? old.filter((d) => d.id !== column.id) : []));
        };
        column.getToggleSortingHandler = () => {
            const canSort = column.getCanSort();
            return (e) => {
                var _a, _b, _c, _d, _e;
                if (!canSort)
                    return;
                (_b = (_a = e).persist) === null || _b === void 0 ? void 0 : _b.call(_a);
                (_c = column.toggleSorting) === null || _c === void 0 ? void 0 : _c.call(column, undefined, column.getCanMultiSort() ? (_e = (_d = table.options).isMultiSortEvent) === null || _e === void 0 ? void 0 : _e.call(_d, e) : false);
            };
        };
    },
    createTable: (table) => {
        table.setSorting = (updater) => { var _a, _b; return (_b = (_a = table.options).onSortingChange) === null || _b === void 0 ? void 0 : _b.call(_a, updater); };
        table.resetSorting = (defaultState) => {
            var _a, _b;
            table.setSorting(defaultState ? [] : ((_b = (_a = table.initialState) === null || _a === void 0 ? void 0 : _a.sorting) !== null && _b !== void 0 ? _b : []));
        };
        table.getPreSortedRowModel = () => table.getGroupedRowModel();
        table.getSortedRowModel = () => {
            if (!table._getSortedRowModel && table.options.getSortedRowModel) {
                table._getSortedRowModel = table.options.getSortedRowModel(table);
            }
            if (table.options.manualSorting || !table._getSortedRowModel) {
                return table.getPreSortedRowModel();
            }
            return table._getSortedRowModel();
        };
    },
};
