import { materializeIncremental } from "../state/checkpointLoad.js";
import { createFrontier, updateFrontier } from "../Frontier.js";
import { buildWriterRef } from "../../utils/RefLayout.js";
import SchemaUnsupportedError from "../../errors/SchemaUnsupportedError.js";
export default class MaterializeCheckpointStrategy {
    runtime;
    constructor(runtime) {
        this.runtime = runtime;
    }
    async materializeAt(checkpointSha) {
        if (this.runtime.deps.openStateSession !== undefined) {
            throw new SchemaUnsupportedError('materializeAt() is not supported on the session-backed runtime line. ' +
                'Run the offline checkpoint migration first.');
        }
        const frontier = await this.buildTargetFrontier();
        const patchLoader = async (_writerId, from, to) => await this.runtime.deps.patches.loadPatchChain(to, from);
        const state = await materializeIncremental({
            persistence: this.runtime.loadPersistence(),
            graphName: this.runtime.deps.graphName,
            checkpointSha,
            targetFrontier: frontier,
            patchLoader,
            codec: this.runtime.deps.codec,
        });
        return await this.runtime.wrapState(state, null, null);
    }
    async buildTargetFrontier() {
        const writers = await this.runtime.deps.patches.discoverWriters();
        const frontier = createFrontier();
        for (const writerId of writers) {
            const ref = buildWriterRef(this.runtime.deps.graphName, writerId);
            const tipSha = await this.runtime.deps.persistence.readRef(ref);
            if (typeof tipSha === 'string' && tipSha.length > 0) {
                updateFrontier(frontier, writerId, tipSha);
            }
        }
        return frontier;
    }
}
