"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.toSimpleTreeSchema = void 0;
const internal_1 = require("@fluidframework/core-utils/internal");
const schemaTypes_js_1 = require("../schemaTypes.js");
const index_js_1 = require("../core/index.js");
const index_js_2 = require("../node-kinds/index.js");
const walkFieldSchema_js_1 = require("../walkFieldSchema.js");
const leafNodeSchema_js_1 = require("../leafNodeSchema.js");
/**
 * Converts an {@link ImplicitFieldSchema} to a "simple" schema representation.
 *
 * @param schema - The schema to convert
 * @param copySchemaObjects - If true, TreeNodeSchema and FieldSchema are copied into plain JavaScript objects. Either way, custom metadata is referenced and not copied.
 *
 * @remarks
 * Given that the Schema types used in {@link ImplicitFieldSchema} already implement the {@link SimpleNodeSchema} interfaces, there are limited use-cases for this function.
 * One possible use-case is converting schema to a more serialization friendly format.
 * This format however is not JSON compatible due to use of Maps and Sets,
 * but it it does not rely on cyclic object references for handling recursive schema and instead uses the `definitions` map.
 *
 * @privateRemarks
 * TODO: once SimpleTreeSchema is stable, {@link TreeViewConfiguration} could implement {@link SimpleTreeSchema} directly.
 * That would provide the non-copying alternative that could expose the value type of the definitions map as {@link TreeNodeSchema}.
 */
function toSimpleTreeSchema(schema, copySchemaObjects) {
    const normalizedSchema = (0, schemaTypes_js_1.normalizeFieldSchema)(schema);
    const definitions = new Map();
    (0, walkFieldSchema_js_1.walkFieldSchema)(normalizedSchema, {
        node: (nodeSchema) => {
            // The set of node kinds is extensible, but the typing of SimpleNodeSchema is not, so we need to check that the schema is one of the known kinds.
            (0, internal_1.assert)(nodeSchema instanceof index_js_2.ArrayNodeSchema ||
                nodeSchema instanceof index_js_2.MapNodeSchema ||
                nodeSchema instanceof leafNodeSchema_js_1.LeafNodeSchema ||
                nodeSchema instanceof index_js_2.ObjectNodeSchema, 0xb60 /* Invalid schema */);
            const outSchema = copySchemaObjects ? copySimpleNodeSchema(nodeSchema) : nodeSchema;
            definitions.set(nodeSchema.identifier, outSchema);
        },
    });
    return {
        root: copySchemaObjects
            ? ({
                allowedTypesIdentifiers: normalizedSchema.allowedTypesIdentifiers,
                kind: normalizedSchema.kind,
                metadata: normalizedSchema.metadata,
                persistedMetadata: normalizedSchema.persistedMetadata,
            })
            : normalizedSchema,
        definitions,
    };
}
exports.toSimpleTreeSchema = toSimpleTreeSchema;
/**
 * Copies a {@link SimpleNodeSchema} into a new plain JavaScript object.
 *
 * @remarks Caches the result on the input schema for future calls.
 */
function copySimpleNodeSchema(schema) {
    const kind = schema.kind;
    switch (kind) {
        case index_js_1.NodeKind.Leaf:
            return copySimpleLeafSchema(schema);
        case index_js_1.NodeKind.Array:
        case index_js_1.NodeKind.Map:
            return copySimpleMapOrArraySchema(schema);
        case index_js_1.NodeKind.Object:
            return copySimpleObjectSchema(schema);
        default:
            (0, internal_1.unreachableCase)(kind);
    }
}
function copySimpleLeafSchema(schema) {
    return {
        kind: index_js_1.NodeKind.Leaf,
        leafKind: schema.leafKind,
        metadata: schema.metadata,
        persistedMetadata: schema.persistedMetadata,
    };
}
function copySimpleMapOrArraySchema(schema) {
    return {
        kind: schema.kind,
        allowedTypesIdentifiers: schema.allowedTypesIdentifiers,
        metadata: schema.metadata,
        persistedMetadata: schema.persistedMetadata,
    };
}
function copySimpleObjectSchema(schema) {
    const fields = new Map();
    for (const [propertyKey, field] of schema.fields) {
        // field already is a SimpleObjectFieldSchema, but copy the subset of the properties needed by this interface to get a clean simple object.
        fields.set(propertyKey, {
            kind: field.kind,
            allowedTypesIdentifiers: field.allowedTypesIdentifiers,
            metadata: field.metadata,
            persistedMetadata: field.persistedMetadata,
            storedKey: field.storedKey,
        });
    }
    return {
        kind: index_js_1.NodeKind.Object,
        fields,
        metadata: schema.metadata,
        persistedMetadata: schema.persistedMetadata,
    };
}
//# sourceMappingURL=viewSchemaToSimpleSchema.js.map