import { spillDependencyKey } from '../../engine-metadata-utils.js';
import { batchOpOrder, createBatch } from '../../replica-state.js';
import { collectTrackedDependents } from './direct-formula-recalc-helpers.js';
import { assertNever } from './operation-change-helpers.js';
export function createOperationDerivedOpApplier(args) {
    const applySpillRangeOp = (op, order) => {
        if (op.kind === 'upsertSpillRange') {
            args.state.workbook.setSpill(op.sheetName, op.address, op.rows, op.cols);
        }
        else {
            args.state.workbook.deleteSpill(op.sheetName, op.address);
        }
        args.setEntityVersionForOp(op, order);
        return collectTrackedDependents(args.reverseSpillEdges, [spillDependencyKey(op.sheetName, op.address)]);
    };
    const applyPivotUpsertOp = (op, order) => {
        const pivot = {
            name: op.name,
            sheetName: op.sheetName,
            address: op.address,
            source: op.source,
            groupBy: op.groupBy,
            values: op.values,
            rows: op.rows,
            cols: op.cols,
        };
        args.state.workbook.setPivot(pivot);
        args.setEntityVersionForOp(op, order);
        return args.materializePivot(pivot);
    };
    const applyPivotDeleteOp = (op, order) => {
        const pivot = args.state.workbook.getPivot(op.sheetName, op.address);
        if (!pivot) {
            args.setEntityVersionForOp(op, order);
            return [];
        }
        const changedPivotOutputs = args.clearOwnedPivot(pivot);
        args.state.workbook.deletePivot(op.sheetName, op.address);
        args.setEntityVersionForOp(op, order);
        return changedPivotOutputs;
    };
    return {
        applySpillRangeOp,
        applyPivotUpsertOp,
        applyPivotDeleteOp,
        applyDerivedOpNow(op) {
            const batch = createBatch(args.state.replicaState, [op]);
            const order = batchOpOrder(batch, 0);
            switch (op.kind) {
                case 'upsertSpillRange':
                case 'deleteSpillRange': {
                    const candidates = applySpillRangeOp(op, order);
                    args.rebindFormulaCells(candidates, 0);
                    return candidates;
                }
                case 'upsertPivotTable':
                    return applyPivotUpsertOp(op, order);
                case 'deletePivotTable':
                    return applyPivotDeleteOp(op, order);
                default:
                    return assertNever(op);
            }
        },
    };
}
//# sourceMappingURL=operation-derived-op-helpers.js.map