import { MAX_COLS, ValueTag } from '@bilig/protocol';
import { addEngineCounter } from '../../perf/engine-counters.js';
export function directAggregateNumericContribution(value) {
    switch (value.tag) {
        case ValueTag.Number:
            return value.value;
        case ValueTag.Boolean:
        case ValueTag.Empty:
        case ValueTag.String:
            return 0;
        case ValueTag.Error:
            return undefined;
    }
}
export function directCriteriaValueString(value) {
    switch (value.tag) {
        case ValueTag.Empty:
            return '';
        case ValueTag.Number:
            return String(Object.is(value.value, -0) ? 0 : value.value);
        case ValueTag.Boolean:
            return value.value ? 'TRUE' : 'FALSE';
        case ValueTag.String:
            return value.value;
        case ValueTag.Error:
            return String(value.code);
    }
}
export function collectTrackedDependents(registry, keys) {
    if (keys.length === 1) {
        const dependents = registry.get(keys[0]);
        return dependents === undefined || dependents.size === 0 ? [] : [...dependents];
    }
    const candidates = new Set();
    keys.forEach((key) => {
        registry.get(key)?.forEach((cellIndex) => {
            candidates.add(cellIndex);
        });
    });
    return [...candidates];
}
export function directCriteriaTouchesPoint(directCriteria, request) {
    if (directCriteria.aggregateRange) {
        const aggregateRange = directCriteria.aggregateRange;
        if (aggregateRange.sheetName === request.sheetName &&
            aggregateRange.col === request.col &&
            request.row >= aggregateRange.rowStart &&
            request.row <= aggregateRange.rowEnd) {
            return true;
        }
    }
    if (request.inputCellIndex !== undefined &&
        directCriteria.offsetOperand?.kind === 'cell' &&
        directCriteria.offsetOperand.cellIndex === request.inputCellIndex) {
        return true;
    }
    return directCriteria.criteriaPairs.some((pair) => {
        if (pair.range.sheetName === request.sheetName &&
            pair.range.col === request.col &&
            request.row >= pair.range.rowStart &&
            request.row <= pair.range.rowEnd) {
            return true;
        }
        if (pair.criterion.kind === 'literal') {
            return false;
        }
        return request.inputCellIndex !== undefined && pair.criterion.cellIndex === request.inputCellIndex;
    });
}
export function composeSingleDisjointExplicitEventChanges(explicitCellIndex, recalculated) {
    if (recalculated.length === 0) {
        return Uint32Array.of(explicitCellIndex);
    }
    const changed = new Uint32Array(recalculated.length + 1);
    changed[0] = explicitCellIndex;
    changed.set(recalculated, 1);
    return changed;
}
export function hasCompleteDirectFormulaDeltas(postRecalcDirectFormulaIndices) {
    return postRecalcDirectFormulaIndices.hasCompleteDeltas();
}
export function directFormulaChangesAreDisjointFromInputs(changedInputArray, changedInputCount, postRecalcDirectFormulaIndices) {
    return !postRecalcDirectFormulaIndices.hasAny(changedInputArray, changedInputCount);
}
export function countDirectFormulaDeltaSkip(formulas, postRecalcDirectFormulaIndices, counters) {
    if (postRecalcDirectFormulaIndices.hasCompleteScalarDeltas()) {
        addEngineCounter(counters, 'directScalarDeltaOnlyRecalcSkips');
        return;
    }
    let sawAggregate = false;
    let sawScalar = false;
    postRecalcDirectFormulaIndices.forEach((cellIndex) => {
        const formula = formulas.get(cellIndex);
        sawAggregate ||= formula?.directAggregate !== undefined || formula?.directCriteria !== undefined;
        sawScalar ||= formula?.directScalar !== undefined;
    });
    if (sawAggregate) {
        addEngineCounter(counters, 'directAggregateDeltaOnlyRecalcSkips');
    }
    if (sawScalar) {
        addEngineCounter(counters, 'directScalarDeltaOnlyRecalcSkips');
    }
}
export function canEvaluatePostRecalcDirectFormulasWithoutKernel(formulas, postRecalcDirectFormulaIndices) {
    if (postRecalcDirectFormulaIndices.size === 0) {
        return false;
    }
    let canEvaluate = true;
    postRecalcDirectFormulaIndices.forEach((cellIndex) => {
        const formula = formulas.get(cellIndex);
        if (formula?.directAggregate === undefined &&
            formula?.directCriteria === undefined &&
            formula?.directLookup === undefined &&
            formula?.directScalar === undefined) {
            canEvaluate = false;
        }
    });
    return canEvaluate;
}
export function lookupImpactCacheKey(sheetId, col) {
    return `${sheetId}:${col}`;
}
export function aggregateColumnDependencyKey(sheetId, col) {
    return sheetId * MAX_COLS + col;
}
//# sourceMappingURL=direct-formula-recalc-helpers.js.map