import defaultCodec from "../../utils/defaultCodec.js";
import { canonicalStringify } from "../../utils/canonicalStringify.js";
import { textEncode } from "../../utils/bytes.js";
import BitmapAccumulator from "./BitmapAccumulator.js";
/**
 * Serializes a frontier Map into CBOR and JSON blobs in the given tree.
 */
function serializeFrontierToTree(frontier, tree, codec) {
    const sorted = {};
    for (const key of Array.from(frontier.keys()).sort()) {
        sorted[key] = frontier.get(key);
    }
    const envelope = { version: 1, writerCount: frontier.size, frontier: sorted };
    tree['frontier.cbor'] = codec.encode(envelope);
    tree['frontier.json'] = textEncode(canonicalStringify(envelope));
}
/**
 * Builder for constructing bitmap indexes in memory.
 *
 * Pure domain class with no infrastructure dependencies. Delegates ID
 * allocation and bitmap accumulation to BitmapAccumulator. Serializes
 * to CBOR shard format (no envelopes — git-cas handles integrity).
 *
 * @example
 * const builder = new BitmapIndexBuilder();
 * builder.addEdge(parentSha, childSha);
 * const tree = await builder.serialize();
 */
export default class BitmapIndexBuilder {
    _codec;
    _accumulator;
    /**
     * Creates a new BitmapIndexBuilder instance.
     */
    constructor(options) {
        const { codec } = options ?? {};
        this._codec = codec ?? defaultCodec;
        this._accumulator = new BitmapAccumulator();
    }
    /** SHA→numeric-ID forward mapping. */
    get shaToId() {
        return this._accumulator.shaToId;
    }
    /** Numeric-ID→SHA reverse mapping. */
    get idToSha() {
        return this._accumulator.idToSha;
    }
    /** Active bitmap map keyed by `{dir}_{sha}`. */
    get bitmaps() {
        return this._accumulator.bitmaps;
    }
    /**
     * Registers a node without adding edges.
     * @returns The assigned numeric ID
     */
    registerNode(sha) {
        return this._accumulator.registerNode(sha);
    }
    /**
     * Adds a directed edge from source to target node.
     */
    addEdge(srcSha, tgtSha) {
        this._accumulator.addEdge(srcSha, tgtSha);
    }
    /**
     * Serializes the index to a tree structure of CBOR buffers.
     *
     * Output structure (sharded by SHA prefix):
     * - `meta_XX.cbor`: {sha: id, ...} for SHAs with prefix XX
     * - `shards_fwd_XX.cbor`: {sha: Uint8Array(bitmap), ...} for forward edges
     * - `shards_rev_XX.cbor`: {sha: Uint8Array(bitmap), ...} for reverse edges
     */
    serialize(options) {
        const { frontier } = options ?? {};
        const tree = {};
        const metaShards = this._accumulator.buildMetaShards();
        for (const [prefix, map] of Object.entries(metaShards)) {
            tree[`meta_${prefix}.cbor`] = this._codec.encode(map);
        }
        const bitmapShards = this._accumulator.serializeBitmapsToShards();
        for (const dir of ['fwd', 'rev']) {
            for (const [prefix, data] of Object.entries(bitmapShards[dir])) {
                tree[`shards_${dir}_${prefix}.cbor`] = this._codec.encode(data);
            }
        }
        if (frontier !== undefined) {
            serializeFrontierToTree(frontier, tree, this._codec);
        }
        return tree;
    }
}
