"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sortToIndexes = exports.sortColumnIdsByOrder = void 0;
function insertAtCorrectIndex(result, colId, visibleColumnsIndexes, hiddenColIds, offset = 0, lastVisibleOffset = 0) {
    const prevColId = result[result.length - 1 - offset];
    if (!prevColId) {
        result.splice(result.length - lastVisibleOffset, 0, colId);
        return;
    }
    if (hiddenColIds.has(prevColId)) {
        insertAtCorrectIndex(result, colId, visibleColumnsIndexes, hiddenColIds, offset + 1, 
        /* do not advance this as, as we've encountered a hidden column*/ lastVisibleOffset);
        return;
    }
    const prevCol_visibilityIndex = visibleColumnsIndexes[prevColId];
    const currentCol_visibilityIndex = visibleColumnsIndexes[colId];
    if (currentCol_visibilityIndex < prevCol_visibilityIndex) {
        insertAtCorrectIndex(result, colId, visibleColumnsIndexes, hiddenColIds, offset + 1, 
        /*make sure we sync with the normal offset, as we've hit a visible col*/ offset + 1);
    }
    else {
        result.splice(result.length - lastVisibleOffset, 0, colId);
    }
}
const ALLOW_MISSING_COLUMNS = true;
/**
 * This method takes a list of column ids (the current order) and the desired column order
 * and returns the column ids in the desired order, while keeping the hidden columns in their original order.
 *
 */
function sortColumnIdsByOrder(columnIds, desiredColumnOrder) {
    const desiredColumnOrderSet = new Set(desiredColumnOrder);
    const columnIdsSet = new Set(columnIds);
    const hiddenColIds = new Set(columnIds.filter((colId) => !desiredColumnOrderSet.has(colId)));
    const visibleColumnsIndexes = desiredColumnOrder.reduce((acc, colId, index) => {
        acc[colId] = index;
        return acc;
    }, {});
    let result = [];
    for (let i = 0, len = columnIds.length; i < len; i++) {
        const colId = columnIds[i];
        const colVisible = visibleColumnsIndexes[colId] != null;
        if (!colVisible) {
            // for cols not present in this layout, we keep them
            // where they are
            result.push(colId);
            continue;
        }
        insertAtCorrectIndex(result, colId, visibleColumnsIndexes, hiddenColIds);
    }
    if (ALLOW_MISSING_COLUMNS) {
        const missingColIdInsertionMapBefore = new Map();
        desiredColumnOrder.forEach((colId, index, arr) => {
            if (!columnIdsSet.has(colId)) {
                let nextColId = null;
                // look for the next colId that is in the columnIdsSet
                for (let i = index + 1; i < arr.length; i++) {
                    if (columnIdsSet.has(arr[i])) {
                        nextColId = arr[i];
                        break;
                    }
                }
                if (nextColId === null || columnIdsSet.has(nextColId)) {
                    const beforeColIds = missingColIdInsertionMapBefore.get(nextColId) || [];
                    missingColIdInsertionMapBefore.set(nextColId, [...beforeColIds, colId]);
                }
            }
        });
        if (missingColIdInsertionMapBefore.size > 0) {
            result = result.flatMap((colId) => {
                const beforeColIds = missingColIdInsertionMapBefore.get(colId) || [];
                return [...beforeColIds, colId];
            });
            if (missingColIdInsertionMapBefore.has(null)) {
                const beforeColIds = missingColIdInsertionMapBefore.get(null) || [];
                result = [...result, ...beforeColIds];
            }
        }
    }
    return result;
}
exports.sortColumnIdsByOrder = sortColumnIdsByOrder;
function sortToIndexes(x, sortIndexes) {
    if (x.length !== sortIndexes.length) {
        throw new Error('x and sortIndexes must be the same length');
    }
    return sortIndexes.map((index) => x[index]);
}
exports.sortToIndexes = sortToIndexes;
