/*!
 * Built by Revolist OU ❤️
 */
import { gatherTrimmedItems } from "../../store/index";
import { GROUP_DEPTH } from "./grouping.const";
import { isGrouping } from "./grouping.service";
export const TRIMMED_GROUPING = 'grouping';
/**
 * Converts a trim row index through the index maps produced while regrouping.
 *
 * Group rows are synthetic, so they may not exist in the first map. When a
 * second map is available, fall back to the original index so trims created
 * against the grouped physical source can still be remapped. If neither path
 * resolves to a number, the caller drops the stale trim entry.
 */
function convertTrimmedIndex(initialIndex, firstLevelMap, secondLevelMap) {
    const sourceIndex = Number.parseInt(initialIndex, 10);
    const firstConversionIndex = firstLevelMap[sourceIndex];
    if (!secondLevelMap) {
        return firstConversionIndex;
    }
    const secondConversionKey = typeof firstConversionIndex === 'number' ? firstConversionIndex : sourceIndex;
    return secondLevelMap[secondConversionKey];
}
/**
 * Prepare trimming updated indexes for grouping
 * @param initiallyTrimed
 * @param firstLevelMap
 * @param secondLevelMap
 */
export function processDoubleConversionTrimmed(initiallyTrimed, firstLevelMap, secondLevelMap) {
    const trimemedOptionsToUpgrade = {};
    /**
     * go through all groups except grouping
     */
    for (let type in initiallyTrimed) {
        if (type === TRIMMED_GROUPING) {
            continue;
        }
        const items = initiallyTrimed[type];
        const newItems = {};
        for (let initialIndex in items) {
            if (!items[initialIndex]) {
                continue;
            }
            /**
             * if item exists we find it in collection
             * we support 2 level of conversions
             */
            const newConversionIndex = convertTrimmedIndex(initialIndex, firstLevelMap, secondLevelMap);
            // Group rows do not exist in the ungrouped index map and must not leak into new trims.
            if (typeof newConversionIndex !== 'number') {
                continue;
            }
            /**
             * if item was trimmed previously
             * trimming makes sense to apply
             */
            newItems[newConversionIndex] = true;
        }
        trimemedOptionsToUpgrade[type] = newItems;
    }
    return trimemedOptionsToUpgrade;
}
function hasVisibleGroupItems(source, trimmed, groupIndex) {
    var _a;
    const depth = (_a = source[groupIndex]) === null || _a === void 0 ? void 0 : _a[GROUP_DEPTH];
    if (depth == null) {
        return false;
    }
    // A group is visible when at least one descendant data row survives filtering.
    for (let i = groupIndex + 1; i < source.length; i++) {
        const model = source[i];
        if (isGrouping(model)) {
            if (model[GROUP_DEPTH] <= depth) {
                break;
            }
            continue;
        }
        if (!trimmed[i]) {
            return true;
        }
    }
    return false;
}
/**
 * Preserves data-row filter results and recalculates group-row visibility
 * from the filtered state of each group's descendant data rows.
 *
 * @param source - Grouped row source that contains group rows and data rows.
 * @param filterTrimmed - Current filter trim map keyed by physical row index.
 * @returns Filter trim map with empty group rows hidden and matching group rows visible.
 */
export function filterOutEmptyGroupRows(source, filterTrimmed) {
    const trimmed = Object.assign({}, filterTrimmed);
    // Recalculate only group rows; data-row filter results are preserved as-is.
    source.forEach((model, index) => {
        if (!isGrouping(model)) {
            return;
        }
        if (hasVisibleGroupItems(source, trimmed, index)) {
            delete trimmed[index];
        }
        else {
            trimmed[index] = true;
        }
    });
    return trimmed;
}
/**
 * Builds grouping trims from an explicit group-to-children map by hiding
 * groups whose children are all hidden by any active trim type.
 *
 * @param allTrimmedGroups - Active trim maps keyed by trim type.
 * @param childrenByGroup - Child row indexes keyed by group row index.
 * @returns Grouping trim map that hides groups without visible children.
 */
export function filterOutEmptyGroups(allTrimmedGroups, childrenByGroup = {}) {
    const trimmedGroup = {};
    const allTrimmed = gatherTrimmedItems(allTrimmedGroups);
    // find is groups are filled
    for (let groupIndex in childrenByGroup) {
        const hasChidlren = childrenByGroup[groupIndex].filter(childIndex => !allTrimmed[childIndex]).length > 0;
        if (!hasChidlren) {
            trimmedGroup[groupIndex] = true;
        }
    }
    return trimmedGroup;
}
