"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.schemaCodecBuilder = void 0;
const internal_1 = require("@fluidframework/core-utils/internal");
const internal_2 = require("@fluidframework/runtime-utils/internal");
const index_js_1 = require("../../codec/index.js");
const index_js_2 = require("../../core/index.js");
const index_js_3 = require("../../util/index.js");
const formatV1_js_1 = require("./formatV1.js");
const formatV2_js_1 = require("./formatV2.js");
function encodeRepoV1(repo) {
    const nodeSchema = encodeNodeSchema(repo, (schema) => schema.encodeV1());
    const rootFieldSchema = (0, index_js_2.encodeFieldSchemaV1)(repo.rootFieldSchema);
    return {
        version: index_js_2.SchemaFormatVersion.v1,
        nodes: nodeSchema,
        root: rootFieldSchema,
    };
}
function encodeRepoV2(repo) {
    const nodeSchema = encodeNodeSchema(repo, (schema) => schema.encodeV2());
    const rootFieldSchema = (0, index_js_2.encodeFieldSchemaV2)(repo.rootFieldSchema);
    return {
        version: index_js_2.SchemaFormatVersion.v2,
        nodes: nodeSchema,
        root: rootFieldSchema,
    };
}
/**
 * Shared logic for encoding node schemas.
 * @param repo - The stored schema to encode.
 * @param encodeValue - A function which encodes a single node schema.
 * @returns The encoded node schema.
 */
function encodeNodeSchema(repo, encodeValue) {
    const nodeSchema = Object.create(null);
    for (const name of [...repo.nodeSchema.keys()].sort()) {
        const schema = repo.nodeSchema.get(name) ?? (0, internal_1.fail)(0xb28 /* missing schema */);
        Object.defineProperty(nodeSchema, name, {
            enumerable: true,
            configurable: true,
            writable: true,
            value: encodeValue(schema),
        });
    }
    return nodeSchema;
}
function decodeV1(f) {
    const nodeSchema = new Map();
    for (const [key, schema] of Object.entries(f.nodes)) {
        const storedSchemaDecoder = index_js_2.storedSchemaDecodeDispatcher.dispatch(schema);
        // No metadata in v1, so pass undefined
        nodeSchema.set((0, index_js_3.brand)(key), storedSchemaDecoder(undefined));
    }
    return {
        rootFieldSchema: (0, index_js_2.decodeFieldSchema)(f.root),
        nodeSchema,
    };
}
function decodeV2(f) {
    const nodeSchema = new Map();
    for (const [key, schema] of Object.entries(f.nodes)) {
        const storedSchemaDecoder = index_js_2.storedSchemaDecodeDispatcher.dispatch(schema.kind);
        // Pass in the node metadata
        nodeSchema.set((0, index_js_3.brand)(key), storedSchemaDecoder(schema.metadata));
    }
    return {
        rootFieldSchema: (0, index_js_2.decodeFieldSchema)(f.root),
        nodeSchema,
    };
}
/**
 * Creates a codec which performs synchronous monolithic encoding of schema content.
 */
exports.schemaCodecBuilder = index_js_1.ClientVersionDispatchingCodecBuilder.build("Schema", [
    {
        minVersionForCollab: internal_2.lowestMinVersionForCollab,
        formatVersion: index_js_2.SchemaFormatVersion.v1,
        codec: {
            encode: (data) => encodeRepoV1(data),
            decode: (data) => decodeV1(data),
            schema: formatV1_js_1.Format,
        },
    },
    {
        minVersionForCollab: index_js_1.FluidClientVersion.v2_43,
        formatVersion: index_js_2.SchemaFormatVersion.v2,
        codec: {
            encode: (data) => encodeRepoV2(data),
            decode: (data) => decodeV2(data),
            schema: formatV2_js_1.Format,
        },
    },
]);
//# sourceMappingURL=codec.js.map