import { ValueTag } from '@bilig/protocol';
import { createColumnIndexStore } from '../indexes/column-index-store.js';
import { createEngineCellStateService } from './services/cell-state-service.js';
import { createEngineEventService } from './services/event-service.js';
import { createEngineChangeSetEmitterService } from './services/change-set-emitter-service.js';
import { createEnginePatchEmitterService } from '../patches/patch-emitter.js';
import { createEngineFormulaEvaluationService } from './services/formula-evaluation-service.js';
import { createCriterionRangeCacheService } from './services/criterion-range-cache-service.js';
import { createExactColumnIndexService } from './services/exact-column-index-service.js';
import { createRangeAggregateCacheService } from './services/range-aggregate-cache-service.js';
import { createSortedColumnSearchService } from './services/sorted-column-search-service.js';
import { createEngineFormulaBindingService } from './services/formula-binding-service.js';
import { createEngineFormulaInitializationService, } from './services/formula-initialization-service.js';
import { createEngineFormulaTemplateNormalizationService } from './services/formula-template-normalization-service.js';
import { createEngineCompiledPlanService } from './services/compiled-plan-service.js';
import { createAggregateStateStore } from '../deps/aggregate-state-store.js';
import { createDepPatternStore } from '../deps/dep-pattern-store.js';
import { createRegionGraph } from '../deps/region-graph.js';
import { createFormulaFamilyStore } from '../formula/formula-family-store.js';
import { createFormulaInstanceTable } from '../formula/formula-instance-table.js';
import { createEngineFormulaGraphService } from './services/formula-graph-service.js';
import { createEngineHistoryService } from './services/history-service.js';
import { createEngineMaintenanceService } from './services/maintenance-service.js';
import { createEngineMutationService } from './services/mutation-service.js';
import { createEngineMutationSupportService } from './services/mutation-support-service.js';
import { createEngineOperationService } from './services/operation-service.js';
import { createEnginePivotService } from './services/pivot-service.js';
import { createEngineDirtyFrontierSchedulerService, } from './services/dirty-frontier-scheduler-service.js';
import { createEngineRuntimeColumnStoreService } from './services/runtime-column-store-service.js';
import { createEngineReplicaSyncService } from './services/replica-sync-service.js';
import { createEngineReadService } from './services/read-service.js';
import { createEngineRecalcService } from './services/recalc-service.js';
import { createEngineRuntimeScratchService } from './services/runtime-scratch-service.js';
import { createEngineSelectionService } from './services/selection-service.js';
import { createEngineSnapshotService } from './services/snapshot-service.js';
import { createEngineStructureService } from './services/structure-service.js';
import { createEngineTraversalService } from './services/traversal-service.js';
import { getRuntimeFormulaSource } from './runtime-formula-source.js';
import { deferKernelSyncNow } from './services/live-kernel-sync-state.js';
import { createEngineFullInvalidationService } from './services/full-invalidation-service.js';
import { runEngineEffect } from './live-effect.js';
export { runEngineEffect, runEngineEffectPromise } from './live-effect.js';
function requireService(service, name) {
    if (service === undefined) {
        throw new Error(`Engine service ${name} is not initialized`);
    }
    return service;
}
export function createEngineServiceRuntime(args) {
    const scratch = createEngineRuntimeScratchService();
    const regionGraph = createRegionGraph({ workbook: args.state.workbook, counters: args.state.counters });
    const traversal = createEngineTraversalService({
        ...args.traversal,
        regionGraph,
    });
    const changeSetEmitter = createEngineChangeSetEmitterService({ state: args.state });
    const patchEmitter = createEnginePatchEmitterService({ state: args.state });
    const events = createEngineEventService(args.state);
    const runtimeColumnStore = createEngineRuntimeColumnStoreService({ state: args.state });
    const columnIndexStore = createColumnIndexStore({ state: args.state, runtimeColumnStore });
    const depPatternStore = createDepPatternStore();
    let aggregateStateStore;
    const getAggregateStateStore = () => (aggregateStateStore ??= createAggregateStateStore({
        workbook: args.state.workbook,
        runtimeColumnStore,
        regionGraph,
    }));
    const compiledPlans = createEngineCompiledPlanService();
    const formulaTemplates = createEngineFormulaTemplateNormalizationService({ counters: args.state.counters });
    const formulaInstances = createFormulaInstanceTable();
    const formulaFamilies = createFormulaFamilyStore();
    const volatileFormulaCells = new Set();
    let criterionCache;
    const getCriterionCache = () => (criterionCache ??= createCriterionRangeCacheService({ runtimeColumnStore, regionGraph, depPatternStore }));
    let aggregateCache;
    const getAggregateCache = () => (aggregateCache ??= createRangeAggregateCacheService({
        regionGraph,
        aggregateStateStore: getAggregateStateStore(),
    }));
    let exactLookupService;
    const getExactLookup = () => (exactLookupService ??= createExactColumnIndexService({ state: args.state, runtimeColumnStore, columnIndexStore }));
    const exactLookup = {
        primeColumnIndex: (request) => getExactLookup().primeColumnIndex(request),
        prepareUniformNumericVectorLookup: (request) => getExactLookup().prepareUniformNumericVectorLookup(request),
        prepareVectorLookup: (request) => getExactLookup().prepareVectorLookup(request),
        findPreparedVectorMatch: (request) => getExactLookup().findPreparedVectorMatch(request),
        findVectorMatch: (request) => getExactLookup().findVectorMatch(request),
        invalidateColumn: (request) => {
            if (exactLookupService) {
                exactLookupService.invalidateColumn(request);
            }
            else {
                columnIndexStore.invalidateColumn(request);
            }
        },
        recordLiteralWrite: (request) => {
            if (exactLookupService) {
                exactLookupService.recordLiteralWrite(request);
            }
            else {
                columnIndexStore.recordLiteralWrite(request, { updateApproximateSummaries: false });
            }
        },
    };
    let sortedLookupService;
    const getSortedLookup = () => (sortedLookupService ??= createSortedColumnSearchService({ state: args.state, runtimeColumnStore, columnIndexStore }));
    const sortedLookup = {
        primeColumnIndex: (request) => getSortedLookup().primeColumnIndex(request),
        prepareVectorLookup: (request) => getSortedLookup().prepareVectorLookup(request),
        findPreparedVectorMatch: (request) => getSortedLookup().findPreparedVectorMatch(request),
        findVectorMatch: (request) => getSortedLookup().findVectorMatch(request),
        invalidateColumn: (request) => {
            if (sortedLookupService) {
                sortedLookupService.invalidateColumn(request);
            }
            else {
                columnIndexStore.invalidateColumn(request);
            }
        },
        recordLiteralWrite: (request) => {
            if (sortedLookupService) {
                sortedLookupService.recordLiteralWrite(request);
            }
            else {
                columnIndexStore.recordLiteralWrite(request);
            }
        },
    };
    const deferKernelSync = (cellIndices) => deferKernelSyncNow({ scratch, cellStoreSize: args.state.workbook.cellStore.size, cellIndices, wasmReady: args.state.wasm.ready });
    const graph = createEngineFormulaGraphService({
        ...args.formulaGraph,
        rebuildCalcChain: () => args.state.scheduler.rebuildChain(args.state.formulas.keys(), args.state.workbook.cellStore),
        notifyCellValueWritten: (cellIndex) => args.state.workbook.notifyCellValueWritten(cellIndex),
        forEachFormulaDependencyCell: (cellIndex, fn) => traversal.forEachFormulaDependencyCellNow(cellIndex, fn),
        collectFormulaDependents: (entityId) => traversal.collectFormulaDependentsNow(entityId),
    });
    let binding;
    let operations;
    let pivot;
    let recalc;
    let formulaInitialization;
    let dirtyScheduler;
    const getDirtyScheduler = () => (dirtyScheduler ??= createEngineDirtyFrontierSchedulerService({
        state: args.state,
        getEntityDependents: (entityId) => traversal.getEntityDependentsNow(entityId),
    }));
    let selection;
    const getSelection = () => {
        selection ??= createEngineSelectionService(args.state);
        return selection;
    };
    const support = createEngineMutationSupportService({
        ...args.mutationSupport,
        removeFormula: (cellIndex) => runEngineEffect(requireService(binding, 'binding').clearFormula(cellIndex)),
        rebindFormulasForSheet: (sheetName, formulaChangedCount, candidates) => runEngineEffect(requireService(binding, 'binding').rebindFormulasForSheet(sheetName, formulaChangedCount, candidates)),
        applyDerivedOp: (op) => runEngineEffect(getOperations().applyDerivedOp(op)),
        collectFormulaDependents: (entityId) => traversal.collectFormulaDependentsNow(entityId),
        getVolatileFormulaCellIndices: () => volatileFormulaCells,
        ensureRecalcScratchCapacity: (size) => runEngineEffect(scratch.ensureRecalcCapacity(size)),
        getChangedInputEpoch: () => scratch.getChangedInputEpochNow(),
        setChangedInputEpoch: (next) => {
            scratch.setChangedInputEpochNow(next);
        },
        getChangedInputSeen: () => scratch.getChangedInputSeenNow(),
        setChangedInputSeen: (next) => {
            scratch.setChangedInputSeenNow(next);
        },
        getChangedInputBuffer: () => scratch.getChangedInputBufferNow(),
        setChangedInputBuffer: (next) => {
            scratch.setChangedInputBufferNow(next);
        },
        getChangedFormulaEpoch: () => scratch.getChangedFormulaEpochNow(),
        setChangedFormulaEpoch: (next) => {
            scratch.setChangedFormulaEpochNow(next);
        },
        getChangedFormulaSeen: () => scratch.getChangedFormulaSeenNow(),
        setChangedFormulaSeen: (next) => {
            scratch.setChangedFormulaSeenNow(next);
        },
        getChangedFormulaBuffer: () => scratch.getChangedFormulaBufferNow(),
        setChangedFormulaBuffer: (next) => {
            scratch.setChangedFormulaBufferNow(next);
        },
        getChangedUnionEpoch: () => scratch.getChangedUnionEpochNow(),
        setChangedUnionEpoch: (next) => {
            scratch.setChangedUnionEpochNow(next);
        },
        getChangedUnionSeen: () => scratch.getChangedUnionSeenNow(),
        setChangedUnionSeen: (next) => {
            scratch.setChangedUnionSeenNow(next);
        },
        getChangedUnion: () => scratch.getChangedUnionNow(),
        setChangedUnion: (next) => {
            scratch.setChangedUnionNow(next);
        },
        getMutationRoots: () => scratch.getMutationRootsNow(),
        setMutationRoots: (next) => {
            scratch.setMutationRootsNow(next);
        },
        getMaterializedCellCount: () => scratch.getMaterializedCellCountNow(),
        setMaterializedCellCount: (next) => {
            scratch.setMaterializedCellCountNow(next);
        },
        getMaterializedCells: () => scratch.getMaterializedCellsNow(),
        setMaterializedCells: (next) => {
            scratch.setMaterializedCellsNow(next);
        },
        getExplicitChangedEpoch: () => scratch.getExplicitChangedEpochNow(),
        setExplicitChangedEpoch: (next) => {
            scratch.setExplicitChangedEpochNow(next);
        },
        getExplicitChangedSeen: () => scratch.getExplicitChangedSeenNow(),
        setExplicitChangedSeen: (next) => {
            scratch.setExplicitChangedSeenNow(next);
        },
        getExplicitChangedBuffer: () => scratch.getExplicitChangedBufferNow(),
        setExplicitChangedBuffer: (next) => {
            scratch.setExplicitChangedBufferNow(next);
        },
        getImpactedFormulaEpoch: () => scratch.getImpactedFormulaEpochNow(),
        setImpactedFormulaEpoch: (next) => {
            scratch.setImpactedFormulaEpochNow(next);
        },
        getImpactedFormulaSeen: () => scratch.getImpactedFormulaSeenNow(),
        setImpactedFormulaSeen: (next) => {
            scratch.setImpactedFormulaSeenNow(next);
        },
        getImpactedFormulaBuffer: () => scratch.getImpactedFormulaBufferNow(),
        setImpactedFormulaBuffer: (next) => {
            scratch.setImpactedFormulaBufferNow(next);
        },
        scheduleWasmProgramSync: () => runEngineEffect(graph.scheduleWasmProgramSync()),
    });
    let evaluation;
    const getEvaluation = () => (evaluation ??= createEngineFormulaEvaluationService({
        state: args.state,
        runtimeColumnStore,
        criterionCache: getCriterionCache(),
        aggregateCache: getAggregateCache(),
        exactLookup,
        sortedLookup,
        materializeSpill: (cellIndex, arrayValue) => support.materializeSpillNow(cellIndex, arrayValue),
        clearOwnedSpill: (cellIndex) => support.clearOwnedSpillNow(cellIndex),
        checkEvaluationBudget: (stepCost) => args.state.checkEvaluationBudget(stepCost),
        resolvePivotData: (sheetName, address, dataField, filters) => runEngineEffect(getPivot().resolvePivotData(sheetName, address, dataField, filters)),
    }));
    binding = createEngineFormulaBindingService({
        ...args.formulaBinding,
        regionGraph,
        compiledPlans,
        formulaInstances,
        formulaFamilies,
        volatileFormulaCells,
        resolveTemplateForCell: (source, row, col) => formulaTemplates.resolveForCell(source, row, col),
        exactLookup,
        sortedLookup,
        ensureCellTracked: (sheetName, address) => support.ensureCellTrackedNow(sheetName, address),
        ensureCellTrackedByCoords: (sheetId, row, col) => support.ensureCellTrackedByCoordsNow(sheetId, row, col),
        markFormulaChanged: (cellIndex, count) => support.markFormulaChangedNow(cellIndex, count),
        resolveStructuredReference: (tableName, columnName, options) => runEngineEffect(getEvaluation().resolveStructuredReference(tableName, columnName, options)),
        resolveSpillReference: (currentSheetName, sheetName, address) => runEngineEffect(getEvaluation().resolveSpillReference(currentSheetName, sheetName, address)),
        forEachSheetCell: (sheetId, fn) => traversal.forEachSheetCellNow(sheetId, fn),
        scheduleWasmProgramSync: () => graph.scheduleWasmProgramSyncNow(),
    });
    let read;
    const getRead = () => (read ??= createEngineReadService({
        state: args.state,
        runtimeColumnStore,
        getFormulaFamilyStructuralSourceTransform: (cellIndex) => binding.getFormulaFamilyStructuralSourceTransformNow(cellIndex),
        forEachFormulaDependencyCell: (cellIndex, fn) => traversal.forEachFormulaDependencyCellNow(cellIndex, fn),
        getEntityDependents: (entityId) => traversal.getEntityDependentsNow(entityId),
        cellToCsvValue: args.cellToCsvValue,
        serializeCsv: args.serializeCsv,
    }));
    let cellState;
    const getCellState = () => (cellState ??= createEngineCellStateService({
        state: args.state,
        getCell: (sheetName, address) => runEngineEffect(getRead().getCell(sheetName, address)),
        getCellByIndex: (cellIndex) => runEngineEffect(getRead().getCellByIndex(cellIndex)),
    }));
    let structure;
    const getStructure = () => (structure ??= createEngineStructureService({
        state: {
            workbook: args.state.workbook,
            formulas: args.state.formulas,
            ranges: args.state.ranges,
            pivotOutputOwners: args.pivotState.pivotOutputOwners,
            counters: args.state.counters,
        },
        captureStoredCellOps: (cellIndex, sheetName, address, sourceSheetName, sourceAddress) => getCellState().captureStoredCellOpsNow(cellIndex, sheetName, address, sourceSheetName, sourceAddress),
        clearOwnedSpill: (cellIndex) => support.clearOwnedSpillNow(cellIndex),
        writeTableHeaderCell: (sheetName, row, col, value) => {
            const sheetId = args.state.workbook.getSheet(sheetName)?.id;
            if (sheetId === undefined) {
                return undefined;
            }
            const { cellIndex } = args.state.workbook.ensureCellAt(sheetId, row, col);
            const currentValue = args.state.workbook.cellStore.getValue(cellIndex, (id) => args.state.strings.get(id));
            const currentFlags = args.state.workbook.cellStore.flags[cellIndex] ?? 0;
            const nextFlags = currentFlags & ~(2 /* CellFlags.HasFormula */ | 4 /* CellFlags.JsOnly */ | 8 /* CellFlags.InCycle */ | 64 /* CellFlags.SpillChild */ | 128 /* CellFlags.PivotOutput */);
            if (currentValue.tag === ValueTag.String && currentValue.value === value && currentFlags === nextFlags) {
                return undefined;
            }
            const stringId = args.state.strings.intern(value);
            binding.clearFormulaNow(cellIndex);
            args.state.workbook.cellStore.setValue(cellIndex, { tag: ValueTag.String, value, stringId }, stringId);
            args.state.workbook.cellStore.flags[cellIndex] = nextFlags;
            return cellIndex;
        },
        removeFormula: (cellIndex) => binding.clearFormulaNow(cellIndex),
        clearOwnedPivot: (pivotRecord) => getPivot().clearOwnedPivotNow(pivotRecord),
        refreshRangeDependencies: (rangeIndices) => binding.refreshRangeDependenciesNow(rangeIndices),
        retargetRangeDependencies: (transaction, rangeIndices) => binding.retargetRangeDependenciesNow(transaction, rangeIndices),
        collectFormulaCellsOwnedBySheet: (sheetName) => binding.collectFormulaCellsOwnedBySheetNow(sheetName),
        forEachFormulaCellOwnedBySheet: (sheetName, fn) => binding.forEachFormulaCellOwnedBySheetNow(sheetName, fn),
        countFormulaSheetMembers: (sheetId) => binding.countFormulaSheetMembersNow(sheetId),
        canUseFormulaFamilyIndex: () => binding.canUseFormulaFamilyIndexNow(),
        tryDeferFormulaFamilyStructuralSourceTransforms: (sheetId, transform, canDeferCellIndex) => binding.tryDeferFormulaFamilyStructuralSourceTransformsNow(sheetId, transform, canDeferCellIndex),
        forEachFormulaFamily: (fn) => binding.forEachFormulaFamilyNow(fn),
        setFormulaFamilyStructuralSourceTransform: (familyId, transform) => binding.setFormulaFamilyStructuralSourceTransformNow(familyId, transform),
        consumeFormulaFamilyStructuralSourceTransforms: () => binding.consumeFormulaFamilyStructuralSourceTransformsNow(),
        peekFormulaFamilyStructuralSourceTransforms: () => binding.peekFormulaFamilyStructuralSourceTransformsNow(),
        collectFormulaCellsReferencingSheet: (sheetName) => binding.collectFormulaCellsReferencingSheetNow(sheetName),
        collectFormulaCellsForDefinedNames: (names) => binding.collectFormulaCellsForDefinedNamesNow(names),
        collectFormulaCellsForTables: (tableNames) => binding.collectFormulaCellsForTablesNow(tableNames),
        retargetDirectAggregateFormulaForStructuralTransform: ({ cellIndex, ownerSheetName, preservesValue }, targetSheetName, transform) => binding.retargetDirectAggregateFormulaForStructuralTransformNow(cellIndex, ownerSheetName, targetSheetName, transform, preservesValue === true),
        retargetDirectAggregateFormulasForStructuralTransform: (inputs, targetSheetName, transform) => binding.retargetDirectAggregateFormulasForStructuralTransformNow(inputs.map((input) => ({
            cellIndex: input.cellIndex,
            ownerSheetName: input.ownerSheetName,
            preservesValue: input.preservesValue === true,
        })), targetSheetName, transform),
        rewriteFormulaCompiledPreservingBinding: ({ cellIndex, ownerSheetName, ownerRow, ownerCol, source, compiled, templateId }) => {
            if (!compiled) {
                return false;
            }
            return binding.rewriteFormulaCompiledPreservingBindingNow(cellIndex, source, compiled, templateId, {
                sheetName: ownerSheetName,
                row: ownerRow,
                col: ownerCol,
            });
        },
        rebindFormulaCells: (inputs) => {
            const pending = inputs.filter(({ cellIndex }) => args.state.formulas.get(cellIndex));
            pending.forEach(({ cellIndex, ownerSheetName, ownerRow, ownerCol, source, compiled, templateId, preservesBinding, preservesValue }) => {
                const ownerPosition = { sheetName: ownerSheetName, row: ownerRow, col: ownerCol };
                try {
                    if (compiled) {
                        if (preservesBinding === true &&
                            preservesValue === true &&
                            binding.rewriteFormulaMetadataPreservingRuntimeNow(cellIndex, source, compiled, templateId, ownerPosition)) {
                            return;
                        }
                        if (preservesBinding === true &&
                            binding.rewriteFormulaCompiledPreservingBindingNow(cellIndex, source, compiled, templateId, ownerPosition)) {
                            return;
                        }
                        binding.bindPreparedFormulaNow(cellIndex, ownerSheetName, source, compiled, templateId);
                    }
                    else {
                        binding.bindFormulaNow(cellIndex, ownerSheetName, source);
                    }
                }
                catch {
                    binding.invalidateFormulaNow(cellIndex);
                }
            });
        },
    }));
    let maintenance;
    const getMaintenance = () => (maintenance ??= createEngineMaintenanceService({
        ...args.maintenance,
        captureSheetCellState: (sheetName) => runEngineEffect(getStructure().captureSheetCellState(sheetName)),
        captureRowRangeCellState: (sheetName, start, count) => runEngineEffect(getStructure().captureRowRangeCellState(sheetName, start, count)),
        captureColumnRangeCellState: (sheetName, start, count) => runEngineEffect(getStructure().captureColumnRangeCellState(sheetName, start, count)),
        setMaterializedCellCount: (next) => {
            scratch.setMaterializedCellCountNow(next);
        },
        resetFormulaRuntimeCaches: () => {
            aggregateStateStore = undefined;
            criterionCache = undefined;
            aggregateCache = undefined;
            exactLookupService = undefined;
            sortedLookupService = undefined;
            evaluation = undefined;
            read = undefined;
            cellState = undefined;
            structure = undefined;
            operations = undefined;
            pivot = undefined;
            recalc = undefined;
            dirtyScheduler = undefined;
            selection = undefined;
            mutation = undefined;
            history = undefined;
            snapshot = undefined;
            sync = undefined;
            runtimeColumnStore.reset();
            columnIndexStore.reset();
            depPatternStore.reset();
            regionGraph.reset();
            compiledPlans.clear();
            formulaTemplates.reset();
            formulaInstances.clear();
            formulaFamilies.clear();
            binding.clearFormulaBookkeepingNow();
            volatileFormulaCells.clear();
        },
        resetWasmState: () => {
            args.state.wasm.resetStoreState();
        },
        scheduleWasmProgramSync: () => runEngineEffect(graph.scheduleWasmProgramSync()),
    }));
    const getRecalc = () => (recalc ??= createEngineRecalcService({
        ...args.recalc,
        beginMutationCollection: () => support.beginMutationCollectionNow(),
        markInputChanged: (cellIndex, count) => support.markInputChangedNow(cellIndex, count),
        markFormulaChanged: (cellIndex, count) => support.markFormulaChangedNow(cellIndex, count),
        markExplicitChanged: (cellIndex, count) => support.markExplicitChangedNow(cellIndex, count),
        composeMutationRoots: (changedInputCount, formulaChangedCount) => support.composeMutationRootsNow(changedInputCount, formulaChangedCount),
        composeEventChanges: (recalculated, explicitChangedCount) => support.composeEventChangesNow(recalculated, explicitChangedCount),
        captureChangedCells: (changedCellIndices) => changeSetEmitter.captureChangedCells(changedCellIndices),
        captureChangedPatches: (changedCellIndices, request) => patchEmitter.captureChangedPatches(changedCellIndices, request),
        unionChangedSets: (...sets) => support.unionChangedSetsNow(...sets),
        composeChangedRootsAndOrdered: (changedRoots, ordered, orderedCount) => support.composeChangedRootsAndOrderedNow(changedRoots, ordered, orderedCount),
        emptyChangedSet: () => support.unionChangedSetsNow(),
        ensureRecalcScratchCapacity: (size) => scratch.ensureRecalcCapacityNow(size),
        getPendingKernelSync: () => scratch.getPendingKernelSyncNow(),
        getDeferredKernelSyncCount: () => scratch.getDeferredKernelSyncCountNow(),
        setDeferredKernelSyncCount: (next) => scratch.setDeferredKernelSyncCountNow(next),
        getDeferredKernelSyncEpoch: () => scratch.getDeferredKernelSyncEpochNow(),
        setDeferredKernelSyncEpoch: (next) => scratch.setDeferredKernelSyncEpochNow(next),
        getDeferredKernelSyncSeen: () => scratch.getDeferredKernelSyncSeenNow(),
        getWasmBatch: () => scratch.getWasmBatchNow(),
        getChangedInputBuffer: () => support.getChangedInputBufferNow(),
        flushWasmProgramSync: () => graph.flushWasmProgramSyncNow(),
        beginEvaluationBudget: (startedAtMs) => args.state.beginEvaluationBudget(startedAtMs),
        endEvaluationBudget: () => args.state.endEvaluationBudget(),
        checkEvaluationBudget: (stepCost) => args.state.checkEvaluationBudget(stepCost),
        dirtyScheduler: getDirtyScheduler(),
        materializeSpill: (cellIndex, arrayValue) => support.materializeSpillNow(cellIndex, arrayValue),
        clearOwnedSpill: (cellIndex) => support.clearOwnedSpillNow(cellIndex),
        evaluateDirectLookupFormula: (cellIndex) => getEvaluation().evaluateDirectLookupFormulaNow(cellIndex),
        evaluateUnsupportedFormula: (cellIndex) => runEngineEffect(getEvaluation().evaluateUnsupportedFormula(cellIndex)),
        materializePivot: (pivotRecord) => getPivot().materializePivotNow(pivotRecord),
        forEachFormulaDependencyCell: (cellIndex, fn) => traversal.forEachFormulaDependencyCellNow(cellIndex, fn),
    }));
    formulaInitialization = createEngineFormulaInitializationService({
        state: args.state,
        beginMutationCollection: () => support.beginMutationCollectionNow(),
        ensureRecalcScratchCapacity: (size) => scratch.ensureRecalcCapacityNow(size),
        ensureCellTrackedByCoords: (sheetId, row, col) => support.ensureCellTrackedByCoordsNow(sheetId, row, col),
        resetMaterializedCellScratch: (expectedSize) => support.resetMaterializedCellScratchNow(expectedSize),
        bindFormula: (cellIndex, ownerSheetName, source) => binding.bindInitialFormulaNow(cellIndex, ownerSheetName, source),
        withInitialFormulaCells: (cellIndices, callback) => binding.withInitialFormulaCellsNow(cellIndices, callback),
        bindPreparedFormula: (cellIndex, ownerSheetName, source, compiled, templateId, options) => binding.bindPreparedFormulaNow(cellIndex, ownerSheetName, source, compiled, templateId, options),
        bindFreshDirectAggregateFormulaRun: (run) => binding.bindFreshDirectAggregateFormulaRunNow(run),
        bindFreshDirectScalarFormulaRun: (run) => binding.bindFreshDirectScalarFormulaRunNow(run),
        upsertFormulaFamilyRun: (run) => {
            formulaFamilies.registerFormulaRun(run);
        },
        registerFreshFormulaFamilyRun: (run) => formulaFamilies.registerFreshUniformRun(run),
        deferFormulaFamilyIndexRebuild: () => binding.deferFormulaFamilyIndexRebuildNow(),
        deferFormulaFamilyIndexRuns: (runs) => binding.deferFormulaFamilyIndexRunsNow(runs),
        deferFormulaInstanceTableRebuild: () => binding.deferFormulaInstanceTableRebuildNow(),
        hydrateFreshFormulaInstances: (records) => binding.hydrateFreshFormulaInstancesNow(records),
        compileTemplateFormula: (source, row, col) => formulaTemplates.resolveForCell(source, row, col),
        clearTemplateFormulaCache: () => formulaTemplates.clear(),
        removeFormula: (cellIndex) => binding.clearFormulaNow(cellIndex),
        setInvalidFormulaValue: (cellIndex) => binding.invalidateFormulaNow(cellIndex),
        markInputChanged: (cellIndex, count) => support.markInputChangedNow(cellIndex, count),
        markFormulaChanged: (cellIndex, count) => support.markFormulaChangedNow(cellIndex, count),
        markVolatileFormulasChanged: (count) => support.markVolatileFormulasChangedNow(count),
        hasVolatileFormulas: () => volatileFormulaCells.size > 0,
        syncDynamicRanges: (formulaChangedCount) => support.syncDynamicRangesNow(formulaChangedCount),
        composeMutationRoots: (changedInputCount, formulaChangedCount) => support.composeMutationRootsNow(changedInputCount, formulaChangedCount),
        getChangedInputBuffer: () => support.getChangedInputBufferNow(),
        getChangedFormulaBuffer: () => scratch.getChangedFormulaBufferNow(),
        rebuildTopoRanks: () => graph.rebuildTopoRanksNow(),
        repairTopoRanks: (changedFormulaCells) => graph.repairTopoRanksNow(changedFormulaCells),
        detectCycles: () => graph.detectCyclesNow(),
        recalculate: (changedRoots, kernelSyncRoots) => getRecalc().recalculateNowSync(changedRoots, kernelSyncRoots),
        deferKernelSync,
        evaluateDirectFormula: (cellIndex) => getEvaluation().evaluateDirectLookupFormulaNow(cellIndex),
        recalculatePreordered: (changedRoots, orderedFormulaCellIndices, orderedFormulaCount, kernelSyncRoots) => getRecalc().recalculatePreorderedNowSync(changedRoots, orderedFormulaCellIndices, orderedFormulaCount, kernelSyncRoots),
        beginEvaluationBudget: (startedAtMs) => args.state.beginEvaluationBudget(startedAtMs),
        endEvaluationBudget: () => args.state.endEvaluationBudget(),
        checkEvaluationBudget: (stepCost) => args.state.checkEvaluationBudget(stepCost),
        reconcilePivotOutputs: (baseChanged, forceAllPivots) => !forceAllPivots && args.pivotState.pivotOutputOwners.size === 0
            ? baseChanged
            : getRecalc().reconcilePivotOutputsNow(baseChanged, forceAllPivots),
        getBatchMutationDepth: () => args.operation.getBatchMutationDepth(),
        setBatchMutationDepth: (next) => {
            args.operation.setBatchMutationDepth(next);
        },
        prepareRegionQueryIndices: () => regionGraph.prepareQueryIndices(),
        writeHydratedFormulaValue: (cellIndex, value) => {
            args.state.workbook.cellStore.flags[cellIndex] =
                (args.state.workbook.cellStore.flags[cellIndex] ?? 0) & ~(64 /* CellFlags.SpillChild */ | 128 /* CellFlags.PivotOutput */);
            args.state.workbook.cellStore.setValue(cellIndex, value, value.tag === ValueTag.String ? args.state.strings.intern(value.value) : 0);
            args.state.workbook.notifyCellValueWritten(cellIndex);
        },
    });
    const getOperations = () => {
        operations ??= createEngineOperationService({
            ...args.operation,
            getSelectionState: () => runEngineEffect(getSelection().getSelectionState()),
            setSelection: (sheetName, address) => runEngineEffect(getSelection().setSelection(sheetName, address)),
            rewriteDefinedNamesForSheetRename: (oldSheetName, newSheetName) => runEngineEffect(getMaintenance().rewriteDefinedNamesForSheetRename(oldSheetName, newSheetName)),
            rewriteCellFormulasForSheetRename: (oldSheetName, newSheetName, formulaChangedCount) => runEngineEffect(binding.rewriteCellFormulasForSheetRename(oldSheetName, newSheetName, formulaChangedCount)),
            rebindDefinedNameDependents: (names, formulaChangedCount) => binding.rebindDefinedNameDependentsNow(names, formulaChangedCount),
            collectFormulaCellsForDefinedNames: (names) => binding.collectFormulaCellsForDefinedNamesNow(names),
            rebindTableDependents: (tableNames, formulaChangedCount) => binding.rebindTableDependentsNow(tableNames, formulaChangedCount),
            collectFormulaCellsForTables: (tableNames) => binding.collectFormulaCellsForTablesNow(tableNames),
            rebindFormulaCells: (candidates, formulaChangedCount) => binding.rebindFormulaCellsNow(candidates, formulaChangedCount),
            hasRegionFormulaSubscriptionsForColumn: (sheetName, col) => {
                const sheet = args.state.workbook.getSheet(sheetName);
                return sheet ? regionGraph.hasFormulaSubscriptionsForColumn(sheet.id, col) : false;
            },
            hasRegionFormulaSubscriptionsForColumnAt: (sheetId, col) => regionGraph.hasFormulaSubscriptionsForColumn(sheetId, col),
            hasRegionFormulaSubscriptionsIntersectingRect: (sheetId, rowStart, rowEnd, colStart, colEnd) => regionGraph.hasFormulaSubscriptionsIntersectingRect(sheetId, rowStart, rowEnd, colStart, colEnd),
            hasRegionFormulaSubscriptions: () => regionGraph.hasFormulaSubscriptions(),
            hasRegionFormulaSubscriptionsOverlappingRange: (sheetId, rowStart, rowEnd, colStart, colEnd) => regionGraph.hasFormulaSubscriptionsOverlappingRange(sheetId, rowStart, rowEnd, colStart, colEnd),
            getRegionFormulaSubscriptionCount: () => regionGraph.getFormulaSubscriptionCount(),
            collectRegionFormulaDependentsForCell: (sheetName, row, col) => {
                const sheet = args.state.workbook.getSheet(sheetName);
                return sheet ? regionGraph.collectFormulaDependentsForCell(sheet.id, row, col) : new Uint32Array();
            },
            collectSingleRegionFormulaDependentForCell: (sheetName, row, col) => {
                const sheet = args.state.workbook.getSheet(sheetName);
                return sheet ? regionGraph.collectSingleFormulaDependentForCell(sheet.id, row, col) : -1;
            },
            collectSingleRegionFormulaDependentForCellAt: (sheetId, row, col) => regionGraph.collectSingleFormulaDependentForCell(sheetId, row, col),
            refreshRangeDependencies: (rangeIndices) => binding.refreshRangeDependenciesNow(rangeIndices),
            rebindFormulasForSheet: (sheetName, formulaChangedCount, candidates) => binding.rebindFormulasForSheetNow(sheetName, formulaChangedCount, candidates),
            materializeDeferredStructuralFormulaSources: () => getStructure().materializeDeferredStructuralFormulaSourcesNow(),
            removeSheetRuntime: (sheetName, explicitChangedCount) => support.removeSheetRuntimeNow(sheetName, explicitChangedCount),
            applyStructuralAxisOp: (op) => getStructure().applyStructuralAxisOpNow(op),
            clearOwnedSpill: (cellIndex) => support.clearOwnedSpillNow(cellIndex),
            clearSpillForCell: (cellIndex) => support.clearSpillForCellNow(cellIndex),
            clearPivotForCell: (cellIndex) => getPivot().clearPivotForCellNow(cellIndex),
            clearOwnedPivot: (pivotRecord) => getPivot().clearOwnedPivotNow(pivotRecord),
            materializePivot: (pivotRecord) => getPivot().materializePivotNow(pivotRecord),
            removeFormula: (cellIndex) => binding.clearFormulaNow(cellIndex),
            bindFormula: (cellIndex, ownerSheetName, source) => binding.bindFormulaNow(cellIndex, ownerSheetName, source),
            rewriteFormulaSourcePreservingBinding: (cellIndex, ownerSheetName, source) => binding.rewriteFormulaSourcePreservingBindingNow(cellIndex, ownerSheetName, source),
            bindPreparedFormula: (cellIndex, ownerSheetName, source, compiled, templateId, options) => binding.bindPreparedFormulaNow(cellIndex, ownerSheetName, source, compiled, templateId, options),
            bindFreshDirectAggregateFormulaRun: (run) => binding.bindFreshDirectAggregateFormulaRunNow(run),
            bindFreshDirectScalarFormulaRun: (run) => binding.bindFreshDirectScalarFormulaRunNow(run),
            registerFreshFormulaFamilyRun: (run) => binding.registerFreshFormulaFamilyRunNow(run),
            upsertFormulaFamilyRun: (run) => binding.upsertFormulaFamilyRunNow(run),
            upsertFreshFormulaInstances: (records) => binding.upsertFreshFormulaInstancesNow(records),
            compileTemplateFormula: (source, row, col) => formulaTemplates.resolveForCell(source, row, col),
            setInvalidFormulaValue: (cellIndex) => binding.invalidateFormulaNow(cellIndex),
            beginEvaluationBudget: (startedAtMs) => args.state.beginEvaluationBudget(startedAtMs),
            endEvaluationBudget: () => args.state.endEvaluationBudget(),
            checkEvaluationBudget: (stepCost) => args.state.checkEvaluationBudget(stepCost),
            beginMutationCollection: (options) => support.beginMutationCollectionNow(options),
            markInputChanged: (cellIndex, count) => support.markInputChangedNow(cellIndex, count),
            markFormulaChanged: (cellIndex, count) => support.markFormulaChangedNow(cellIndex, count),
            markVolatileFormulasChanged: (count) => support.markVolatileFormulasChangedNow(count),
            hasVolatileFormulas: () => volatileFormulaCells.size > 0,
            markSpillRootsChanged: (cellIndices, count) => support.markSpillRootsChangedNow(cellIndices, count),
            markPivotRootsChanged: (cellIndices, count) => support.markPivotRootsChangedNow(cellIndices, count),
            markExplicitChanged: (cellIndex, count) => support.markExplicitChangedNow(cellIndex, count),
            composeMutationRoots: (changedInputCount, formulaChangedCount) => support.composeMutationRootsNow(changedInputCount, formulaChangedCount),
            composeEventChanges: (recalculated, explicitChangedCount) => support.composeEventChangesNow(recalculated, explicitChangedCount),
            composeDisjointEventChanges: (recalculated, explicitChangedCount) => support.composeDisjointEventChangesNow(recalculated, explicitChangedCount),
            captureChangedCells: (changedCellIndices) => changeSetEmitter.captureChangedCells(changedCellIndices),
            captureChangedPatches: (changedCellIndices, request) => patchEmitter.captureChangedPatches(changedCellIndices, request),
            getChangedInputBuffer: () => support.getChangedInputBufferNow(),
            getChangedFormulaBuffer: () => scratch.getChangedFormulaBufferNow(),
            ensureRecalcScratchCapacity: (size) => scratch.ensureRecalcCapacityNow(size),
            estimatePotentialNewCells: (ops) => runEngineEffect(getMaintenance().estimatePotentialNewCells(ops)),
            ensureCellTracked: (sheetName, address) => support.ensureCellTrackedNow(sheetName, address),
            resetMaterializedCellScratch: (expectedSize) => support.resetMaterializedCellScratchNow(expectedSize),
            syncDynamicRanges: (formulaChangedCount) => support.syncDynamicRangesNow(formulaChangedCount),
            rebuildTopoRanks: () => graph.rebuildTopoRanksNow(),
            repairTopoRanks: (changedFormulaCells) => graph.repairTopoRanksNow(changedFormulaCells),
            detectCycles: () => graph.detectCyclesNow(),
            recalculate: (changedRoots, kernelSyncRoots) => getRecalc().recalculateNowSync(changedRoots, kernelSyncRoots),
            deferKernelSync,
            evaluateDirectFormula: (cellIndex) => getEvaluation().evaluateDirectLookupFormulaNow(cellIndex),
            evaluateFormulaCell: (cellIndex) => getEvaluation().evaluateUnsupportedFormulaNow(cellIndex),
            exactLookup,
            sortedLookup,
            reconcilePivotOutputs: (baseChanged, forceAllPivots) => !forceAllPivots && args.pivotState.pivotOutputOwners.size === 0
                ? baseChanged
                : getRecalc().reconcilePivotOutputsNow(baseChanged, forceAllPivots),
            prepareRegionQueryIndices: () => regionGraph.prepareQueryIndices(),
            getEntityDependents: (entityId) => traversal.getEntityDependentsNow(entityId),
            getSingleEntityDependent: (entityId) => traversal.getSingleEntityDependentNow(entityId),
            getCellDependents: (cellIndex) => traversal.getCellDependentsNow(cellIndex),
            getSingleCellDependent: (cellIndex) => traversal.getSingleCellDependentNow(cellIndex),
            forEachFormulaDependencyCell: (cellIndex, fn) => traversal.forEachFormulaDependencyCellNow(cellIndex, fn),
            collectFormulaDependents: (entityId) => traversal.collectFormulaDependentsNow(entityId),
            noteExactLookupLiteralWrite: (request) => exactLookup.recordLiteralWrite(request),
            noteAggregateLiteralWrite: (request) => getAggregateStateStore().noteLiteralWrite(request),
            noteSortedLookupLiteralWrite: (request) => sortedLookup.recordLiteralWrite(request),
            invalidateExactLookupColumn: (request) => exactLookup.invalidateColumn(request),
            invalidateAggregateColumn: (request) => getAggregateStateStore().invalidateColumn(request.sheetName, request.col),
            invalidateSortedLookupColumn: (request) => sortedLookup.invalidateColumn(request),
        });
        return operations;
    };
    let mutation;
    const getMutation = () => {
        mutation ??= createEngineMutationService({
            state: args.state,
            captureSheetCellState: (sheetName) => runEngineEffect(getMaintenance().captureSheetCellState(sheetName)),
            captureRowRangeCellState: (sheetName, start, count) => runEngineEffect(getMaintenance().captureRowRangeCellState(sheetName, start, count)),
            captureColumnRangeCellState: (sheetName, start, count) => runEngineEffect(getMaintenance().captureColumnRangeCellState(sheetName, start, count)),
            captureStoredCellOps: (cellIndex, sheetName, address) => getCellState().captureStoredCellOpsNow(cellIndex, sheetName, address),
            restoreCellOps: (sheetName, address) => getCellState().restoreCellOpsNow(sheetName, address),
            getCellByIndex: args.getCellByIndex,
            getFormulaFamilyStructuralSourceTransform: (cellIndex) => binding.getFormulaFamilyStructuralSourceTransformNow(cellIndex),
            hasFormulaFamilyStructuralSourceTransforms: () => binding.hasFormulaFamilyStructuralSourceTransformsNow(),
            readRangeCells: (range) => getCellState().readRangeCellsNow(range),
            toCellStateOps: (sheetName, address, snapshot, sourceSheetName, sourceAddress) => getCellState().toCellStateOpsNow(sheetName, address, snapshot, sourceSheetName, sourceAddress),
            applyBatchNow: (batch, source, potentialNewCells, preparedCellAddressesByOpIndex) => getOperations().applyBatchNow(batch, source, potentialNewCells, preparedCellAddressesByOpIndex),
            applyLocalSingleStructuralAxisOpWithoutBatchNow: (op, options) => getOperations().applyLocalSingleStructuralAxisOpWithoutBatchNow(op, options),
            applyCellMutationsAtBatchNow: (refs, batch, source, potentialNewCells) => getOperations().applyCellMutationsAtNow(refs, batch, source, potentialNewCells),
            applyExistingNumericCellMutationsAtBatchNow: (record, batch, source) => getOperations().applyExistingNumericCellMutationsAtNow(record, batch, source),
            applyExistingNumericCellMutationAtNow: (request) => getOperations().applyExistingNumericCellMutationAtNow(request),
            applyExistingLiteralCellMutationAtNow: (request) => getOperations().applyExistingLiteralCellMutationAtNow(request),
            hasExternallyVisibleLocalMutationObservers: () => args.state.events.hasListeners() ||
                args.state.events.hasTrackedListeners() ||
                args.state.events.hasCellListeners() ||
                (args.state.batchListeners?.size ?? 0) > 0 ||
                args.state.getSyncClientConnection() !== null,
        });
        return mutation;
    };
    let history;
    const getHistory = () => {
        history ??= createEngineHistoryService({
            state: args.state,
            executeTransaction: (transaction, source) => runEngineEffect(getMutation().executeTransaction(transaction, source)),
        });
        return history;
    };
    const fullInvalidation = createEngineFullInvalidationService({ state: args.state, patchEmitter });
    const getPivot = () => {
        pivot ??= createEnginePivotService({
            ...args.pivot,
            ensureCellTrackedByCoords: (sheetId, row, col) => support.ensureCellTrackedByCoordsNow(sheetId, row, col),
            forEachSheetCell: (sheetId, fn) => traversal.forEachSheetCellNow(sheetId, fn),
            flushDeferredKernelSync: () => {
                const deferredCount = scratch.getDeferredKernelSyncCountNow();
                if (deferredCount === 0 || !args.state.wasm.ready) {
                    return;
                }
                args.state.wasm.syncFromStore(args.state.workbook.cellStore, scratch.getPendingKernelSyncNow().subarray(0, deferredCount));
                scratch.setDeferredKernelSyncCountNow(0);
                let nextEpoch = scratch.getDeferredKernelSyncEpochNow() + 1;
                if (nextEpoch === 0xffff_ffff) {
                    nextEpoch = 1;
                    scratch.getDeferredKernelSyncSeenNow().fill(0);
                }
                scratch.setDeferredKernelSyncEpochNow(nextEpoch);
            },
            scheduleWasmProgramSync: () => graph.scheduleWasmProgramSyncNow(),
            flushWasmProgramSync: () => graph.flushWasmProgramSyncNow(),
            applyDerivedOp: (op) => runEngineEffect(getOperations().applyDerivedOp(op)),
        });
        return pivot;
    };
    let snapshot;
    const getSnapshot = () => {
        snapshot ??= createEngineSnapshotService({
            state: args.state,
            getCellByIndex: args.getCellByIndex,
            resetWorkbook: (workbookName) => runEngineEffect(getMaintenance().resetWorkbook(workbookName)),
            exportTemplateBank: () => formulaTemplates.listTemplates(),
            exportFormulaInstances: () => binding.exportFormulaInstancesNow().flatMap((record) => {
                const sheetId = args.state.workbook.cellStore.sheetIds[record.cellIndex];
                const position = args.state.workbook.getCellPosition(record.cellIndex);
                const formula = args.state.formulas.get(record.cellIndex);
                if (sheetId === undefined || !position) {
                    return [];
                }
                const sheetName = args.state.workbook.getSheetNameById(sheetId);
                if (!sheetName) {
                    return [];
                }
                return [
                    {
                        ...record,
                        sheetName,
                        row: position.row,
                        col: position.col,
                        source: formula
                            ? getRuntimeFormulaSource(formula, formulaFamilies.getStructuralSourceTransform(record.cellIndex))
                            : record.source,
                        ...(formula?.templateId !== undefined
                            ? { templateId: formula.templateId }
                            : record.templateId !== undefined
                                ? { templateId: record.templateId }
                                : {}),
                    },
                ];
            }),
            exportFormulaFamilyRuns: () => {
                binding.getFormulaFamilyStatsNow();
                return formulaFamilies.listFamilies().flatMap((family) => {
                    const sheetName = args.state.workbook.getSheetNameById(family.sheetId);
                    if (!sheetName) {
                        return [];
                    }
                    return family.runs.map((run) => ({
                        sheetName,
                        templateId: family.templateId,
                        shapeKey: family.shapeKey,
                        axis: run.axis,
                        fixedIndex: run.fixedIndex,
                        start: run.start,
                        step: run.step,
                        cellIndices: run.cellIndices,
                    }));
                });
            },
            hydrateTemplateBank: (templates) => formulaTemplates.hydrateTemplates(templates),
            resolveTemplateById: (templateId, source, row, col) => formulaTemplates.resolveTrustedByTemplateId(templateId, source, row, col),
            resolveTemplateForCell: (source, row, col) => formulaTemplates.resolveForCell(source, row, col),
            beginEvaluationBudget: (startedAtMs) => args.state.beginEvaluationBudget(startedAtMs),
            endEvaluationBudget: () => args.state.endEvaluationBudget(),
            checkEvaluationBudget: (stepCost) => args.state.checkEvaluationBudget(stepCost),
            initializeCellFormulasAt: (refs, potentialNewCells) => requireService(formulaInitialization, 'formulaInitialization').initializeCellFormulasAtNow(refs, potentialNewCells),
            initializeFormulaSourcesAt: (refs, potentialNewCells) => requireService(formulaInitialization, 'formulaInitialization').initializeFormulaSourcesAtNow(refs, potentialNewCells),
            initializePreparedCellFormulasAt: (refs, potentialNewCells) => requireService(formulaInitialization, 'formulaInitialization').initializePreparedCellFormulasAtNow(refs, potentialNewCells),
            initializeHydratedPreparedCellFormulasAt: (refs, potentialNewCells) => requireService(formulaInitialization, 'formulaInitialization').initializeHydratedPreparedCellFormulasAtNow(refs, potentialNewCells),
            initializeCachedFormulaSourcesAt: (refs, potentialNewCells) => requireService(formulaInitialization, 'formulaInitialization').initializeCachedFormulaSourcesAtNow(refs, potentialNewCells),
            materializePivot: (pivotRecord) => getPivot().materializePivotNow(pivotRecord),
            emitFullInvalidation: fullInvalidation.emitFullSnapshotInvalidation,
        });
        return snapshot;
    };
    let sync;
    const getSync = () => {
        sync ??= createEngineReplicaSyncService({
            state: args.state,
            applyRemoteBatchNow: (batch) => runEngineEffect(getOperations().applyBatch(batch, 'remote')),
            applyRemoteSnapshot: args.applyRemoteSnapshot,
        });
        return sync;
    };
    return {
        get cellState() {
            return getCellState();
        },
        get maintenance() {
            return getMaintenance();
        },
        traversal,
        deferKernelSync,
        hasVolatileFormulas: () => volatileFormulaCells.size > 0,
        hasRegionFormulaSubscriptions: () => regionGraph.hasFormulaSubscriptions(),
        events,
        get evaluation() {
            return getEvaluation();
        },
        get selection() {
            return getSelection();
        },
        binding,
        formulaFamilies,
        formulaInitialization,
        graph,
        get history() {
            return getHistory();
        },
        support,
        get read() {
            return getRead();
        },
        get recalc() {
            return getRecalc();
        },
        get structure() {
            return getStructure();
        },
        get mutation() {
            return getMutation();
        },
        get operations() {
            return getOperations();
        },
        get pivot() {
            return getPivot();
        },
        get snapshot() {
            return getSnapshot();
        },
        get sync() {
            return getSync();
        },
    };
}
//# sourceMappingURL=live.js.map