import { Effect } from 'effect';
import { growUint32 } from '../../engine-buffer-utils.js';
import { EngineRuntimeScratchError } from '../errors.js';
export const INITIAL_RUNTIME_SCRATCH_CAPACITY = 16;
function scratchCapacityFor(required) {
    let capacity = INITIAL_RUNTIME_SCRATCH_CAPACITY;
    while (capacity < required) {
        capacity *= 2;
    }
    return capacity;
}
function createScratchBuffer(required = INITIAL_RUNTIME_SCRATCH_CAPACITY) {
    return new Uint32Array(scratchCapacityFor(required));
}
function growScratchBuffer(buffer, size) {
    if (size <= (buffer?.length ?? INITIAL_RUNTIME_SCRATCH_CAPACITY)) {
        return buffer;
    }
    if (buffer === undefined) {
        return createScratchBuffer(size);
    }
    return growUint32(buffer, size);
}
function scratchErrorMessage(message, cause) {
    return cause instanceof Error && cause.message.length > 0 ? cause.message : message;
}
class EngineRuntimeScratchServiceImpl {
    pendingKernelSync;
    deferredKernelSyncCount = 0;
    deferredKernelSyncEpoch = 1;
    deferredKernelSyncSeen;
    wasmBatch;
    mutationRoots;
    changedInputEpoch = 1;
    changedInputSeen;
    changedInputBuffer;
    changedFormulaEpoch = 1;
    changedFormulaSeen;
    changedFormulaBuffer;
    changedUnionEpoch = 1;
    changedUnionSeen;
    changedUnion;
    materializedCellCount = 0;
    materializedCells;
    explicitChangedEpoch = 1;
    explicitChangedSeen;
    explicitChangedBuffer;
    impactedFormulaEpoch = 1;
    impactedFormulaSeen;
    impactedFormulaBuffer;
    ensureRecalcCapacity(size) {
        return Effect.try({
            try: () => {
                this.ensureRecalcCapacityNow(size);
            },
            catch: (cause) => new EngineRuntimeScratchError({
                message: scratchErrorMessage('Failed to ensure recalc scratch capacity', cause),
                cause,
            }),
        });
    }
    ensureRecalcCapacityNow(size) {
        this.mutationRoots = growScratchBuffer(this.mutationRoots, size);
        this.changedInputSeen = growScratchBuffer(this.changedInputSeen, size);
        this.changedInputBuffer = growScratchBuffer(this.changedInputBuffer, size);
        this.changedFormulaSeen = growScratchBuffer(this.changedFormulaSeen, size);
        this.changedFormulaBuffer = growScratchBuffer(this.changedFormulaBuffer, size);
        this.pendingKernelSync = growScratchBuffer(this.pendingKernelSync, size);
        this.deferredKernelSyncSeen = growScratchBuffer(this.deferredKernelSyncSeen, size);
        this.wasmBatch = growScratchBuffer(this.wasmBatch, size);
        this.changedUnion = growScratchBuffer(this.changedUnion, size);
        this.changedUnionSeen = growScratchBuffer(this.changedUnionSeen, size);
        this.materializedCells = growScratchBuffer(this.materializedCells, size);
        this.explicitChangedSeen = growScratchBuffer(this.explicitChangedSeen, size);
        this.explicitChangedBuffer = growScratchBuffer(this.explicitChangedBuffer, size);
        this.impactedFormulaSeen = growScratchBuffer(this.impactedFormulaSeen, size);
        this.impactedFormulaBuffer = growScratchBuffer(this.impactedFormulaBuffer, size);
    }
    getPendingKernelSyncNow() {
        return (this.pendingKernelSync ??= createScratchBuffer());
    }
    setPendingKernelSyncNow(next) {
        this.pendingKernelSync = next;
    }
    getDeferredKernelSyncCountNow() {
        return this.deferredKernelSyncCount;
    }
    setDeferredKernelSyncCountNow(next) {
        this.deferredKernelSyncCount = next;
    }
    getDeferredKernelSyncEpochNow() {
        return this.deferredKernelSyncEpoch;
    }
    setDeferredKernelSyncEpochNow(next) {
        this.deferredKernelSyncEpoch = next;
    }
    getDeferredKernelSyncSeenNow() {
        return (this.deferredKernelSyncSeen ??= createScratchBuffer());
    }
    setDeferredKernelSyncSeenNow(next) {
        this.deferredKernelSyncSeen = next;
    }
    getWasmBatchNow() {
        return (this.wasmBatch ??= createScratchBuffer());
    }
    setWasmBatchNow(next) {
        this.wasmBatch = next;
    }
    getMutationRootsNow() {
        return (this.mutationRoots ??= createScratchBuffer());
    }
    setMutationRootsNow(next) {
        this.mutationRoots = next;
    }
    getChangedInputEpochNow() {
        return this.changedInputEpoch;
    }
    setChangedInputEpochNow(next) {
        this.changedInputEpoch = next;
    }
    getChangedInputSeenNow() {
        return (this.changedInputSeen ??= createScratchBuffer());
    }
    setChangedInputSeenNow(next) {
        this.changedInputSeen = next;
    }
    getChangedInputBufferNow() {
        return (this.changedInputBuffer ??= createScratchBuffer());
    }
    setChangedInputBufferNow(next) {
        this.changedInputBuffer = next;
    }
    getChangedFormulaEpochNow() {
        return this.changedFormulaEpoch;
    }
    setChangedFormulaEpochNow(next) {
        this.changedFormulaEpoch = next;
    }
    getChangedFormulaSeenNow() {
        return (this.changedFormulaSeen ??= createScratchBuffer());
    }
    setChangedFormulaSeenNow(next) {
        this.changedFormulaSeen = next;
    }
    getChangedFormulaBufferNow() {
        return (this.changedFormulaBuffer ??= createScratchBuffer());
    }
    setChangedFormulaBufferNow(next) {
        this.changedFormulaBuffer = next;
    }
    getChangedUnionEpochNow() {
        return this.changedUnionEpoch;
    }
    setChangedUnionEpochNow(next) {
        this.changedUnionEpoch = next;
    }
    getChangedUnionSeenNow() {
        return (this.changedUnionSeen ??= createScratchBuffer());
    }
    setChangedUnionSeenNow(next) {
        this.changedUnionSeen = next;
    }
    getChangedUnionNow() {
        return (this.changedUnion ??= createScratchBuffer());
    }
    setChangedUnionNow(next) {
        this.changedUnion = next;
    }
    getMaterializedCellCountNow() {
        return this.materializedCellCount;
    }
    setMaterializedCellCountNow(next) {
        this.materializedCellCount = next;
    }
    getMaterializedCellsNow() {
        return (this.materializedCells ??= createScratchBuffer());
    }
    setMaterializedCellsNow(next) {
        this.materializedCells = next;
    }
    getExplicitChangedEpochNow() {
        return this.explicitChangedEpoch;
    }
    setExplicitChangedEpochNow(next) {
        this.explicitChangedEpoch = next;
    }
    getExplicitChangedSeenNow() {
        return (this.explicitChangedSeen ??= createScratchBuffer());
    }
    setExplicitChangedSeenNow(next) {
        this.explicitChangedSeen = next;
    }
    getExplicitChangedBufferNow() {
        return (this.explicitChangedBuffer ??= createScratchBuffer());
    }
    setExplicitChangedBufferNow(next) {
        this.explicitChangedBuffer = next;
    }
    getImpactedFormulaEpochNow() {
        return this.impactedFormulaEpoch;
    }
    setImpactedFormulaEpochNow(next) {
        this.impactedFormulaEpoch = next;
    }
    getImpactedFormulaSeenNow() {
        return (this.impactedFormulaSeen ??= createScratchBuffer());
    }
    setImpactedFormulaSeenNow(next) {
        this.impactedFormulaSeen = next;
    }
    getImpactedFormulaBufferNow() {
        return (this.impactedFormulaBuffer ??= createScratchBuffer());
    }
    setImpactedFormulaBufferNow(next) {
        this.impactedFormulaBuffer = next;
    }
}
export function createEngineRuntimeScratchService() {
    return new EngineRuntimeScratchServiceImpl();
}
//# sourceMappingURL=runtime-scratch-service.js.map