import { parseCellAddress } from '@bilig/formula';
import { cellTouchesOperationPivotSource } from './operation-pivot-source-helpers.js';
import { rethrowFatalFormulaBindingError } from './formula-binding-error-policy.js';
export function applyBatchSetCellFormulaOp(request) {
    const args = request.serviceArgs;
    const { op, preparedCellAddress } = request;
    const parsedAddress = parseCellAddress(op.address, op.sheetName);
    const sheetId = args.state.workbook.getSheet(op.sheetName)?.id;
    let changedInputCount = request.changedInputCount;
    let formulaChangedCount = request.formulaChangedCount;
    let explicitChangedCount = request.explicitChangedCount;
    let topologyChanged = request.topologyChanged;
    let refreshAllPivots = request.refreshAllPivots;
    let compileMs = request.compileMs;
    if (!request.isRestore &&
        cellTouchesOperationPivotSource({
            workbook: args.state.workbook,
            sheetName: op.sheetName,
            row: parsedAddress.row,
            col: parsedAddress.col,
        })) {
        refreshAllPivots = true;
    }
    args.invalidateExactLookupColumn({ sheetName: op.sheetName, col: parsedAddress.col });
    args.invalidateSortedLookupColumn({ sheetName: op.sheetName, col: parsedAddress.col });
    if (!request.isRestore) {
        const existingIndex = request.preparedCells.getExistingCellIndex(op.sheetName, op.address, preparedCellAddress);
        if (existingIndex !== undefined) {
            changedInputCount = args.markPivotRootsChanged(args.clearPivotForCell(existingIndex), changedInputCount);
        }
    }
    const cellIndex = request.preparedCells.ensureCellTracked(op.sheetName, op.address, preparedCellAddress);
    const priorHadFormula = args.state.formulas.get(cellIndex) !== undefined;
    const oldFormulaNumber = !request.isRestore && priorHadFormula ? request.readExactNumericValueForLookup(cellIndex) : undefined;
    args.state.workbook.cellStore.flags[cellIndex] = (args.state.workbook.cellStore.flags[cellIndex] ?? 0) & ~256 /* CellFlags.AuthoredBlank */;
    if (!request.isRestore) {
        const clearedSpill = args.clearSpillForCell(cellIndex);
        changedInputCount = args.markSpillRootsChanged(clearedSpill.changedCellIndices, changedInputCount);
        if (clearedSpill.ownerCellIndex !== undefined) {
            formulaChangedCount = args.markFormulaChanged(clearedSpill.ownerCellIndex, formulaChangedCount);
        }
    }
    const compileStarted = request.isRestore ? 0 : performance.now();
    const hasFormulaColumnAggregateDependents = sheetId !== undefined && request.hasTrackedDirectRangeDependents(sheetId, parsedAddress.col);
    try {
        const priorDirectScalarFormula = args.state.formulas.get(cellIndex)?.directScalar !== undefined;
        const canRewriteFormulaPreservingBinding = !request.isRestore &&
            priorDirectScalarFormula &&
            sheetId !== undefined &&
            !request.hasTrackedExactLookupDependents(sheetId, parsedAddress.col) &&
            !request.hasTrackedSortedLookupDependents(sheetId, parsedAddress.col) &&
            !hasFormulaColumnAggregateDependents &&
            args.rewriteFormulaSourcePreservingBinding !== undefined;
        const changedTopology = canRewriteFormulaPreservingBinding
            ? args.rewriteFormulaSourcePreservingBinding(cellIndex, op.sheetName, op.formula)
                ? false
                : args.bindFormula(cellIndex, op.sheetName, op.formula)
            : args.bindFormula(cellIndex, op.sheetName, op.formula);
        if (hasFormulaColumnAggregateDependents) {
            args.invalidateAggregateColumn({ sheetName: op.sheetName, col: parsedAddress.col });
        }
        request.clearLookupImpactCaches();
        if (!request.isRestore) {
            compileMs += performance.now() - compileStarted;
        }
        changedInputCount = args.markInputChanged(cellIndex, changedInputCount);
        const handledFormulaReplacementAsDirectDelta = priorHadFormula &&
            sheetId !== undefined &&
            !request.hasTrackedExactLookupDependents(sheetId, parsedAddress.col) &&
            !request.hasTrackedSortedLookupDependents(sheetId, parsedAddress.col) &&
            !hasFormulaColumnAggregateDependents &&
            request.tryApplyFormulaReplacementAsDirectScalarDeltaRoot({
                cellIndex,
                oldNumber: oldFormulaNumber,
                changedTopology,
                postRecalcDirectFormulaIndices: request.postRecalcDirectFormulaIndices,
                postRecalcDirectFormulaMetrics: request.postRecalcDirectFormulaMetrics,
            });
        if (!handledFormulaReplacementAsDirectDelta) {
            formulaChangedCount = args.markFormulaChanged(cellIndex, formulaChangedCount);
        }
        topologyChanged = topologyChanged || changedTopology;
        if (!priorHadFormula) {
            formulaChangedCount = request.refreshDependentRangesAndRebindFormulaDependents(cellIndex, formulaChangedCount);
            topologyChanged = true;
        }
        const aggregateDependents = hasFormulaColumnAggregateDependents
            ? request
                .collectAffectedDirectRangeDependents({
                sheetName: op.sheetName,
                row: parsedAddress.row,
                col: parsedAddress.col,
            })
                .filter((candidate) => candidate !== cellIndex)
            : [];
        if (aggregateDependents.length > 0) {
            formulaChangedCount = args.rebindFormulaCells(aggregateDependents, formulaChangedCount);
            for (let index = 0; index < aggregateDependents.length; index += 1) {
                request.postRecalcDirectFormulaIndices.add(aggregateDependents[index]);
                formulaChangedCount = args.markFormulaChanged(aggregateDependents[index], formulaChangedCount);
                changedInputCount = args.markInputChanged(aggregateDependents[index], changedInputCount);
            }
            topologyChanged = true;
        }
    }
    catch (error) {
        rethrowFatalFormulaBindingError(error);
        if (!request.isRestore) {
            compileMs += performance.now() - compileStarted;
        }
        topologyChanged = args.removeFormula(cellIndex) || topologyChanged;
        args.setInvalidFormulaValue(cellIndex);
        changedInputCount = args.markInputChanged(cellIndex, changedInputCount);
    }
    if (!request.isRestore) {
        explicitChangedCount = args.markExplicitChanged(cellIndex, explicitChangedCount);
        request.setEntityVersionForOp(op, request.order);
    }
    return { changedInputCount, formulaChangedCount, explicitChangedCount, topologyChanged, refreshAllPivots, compileMs };
}
//# sourceMappingURL=operation-batch-cell-formula-mutations.js.map