"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFromCursor = exports.cursorFromInsertable = exports.createFromInsertable = void 0;
const internal_1 = require("@fluidframework/core-utils/internal");
const index_js_1 = require("../core/index.js");
const index_js_2 = require("../../feature-libraries/index.js");
const index_js_3 = require("../../feature-libraries/index.js");
const toStoredSchema_js_1 = require("../toStoredSchema.js");
const toMapTree_js_1 = require("../toMapTree.js");
const createContext_js_1 = require("../createContext.js");
const objectNode_js_1 = require("../objectNode.js");
/**
 * Construct tree content that is compatible with the field defined by the provided `schema`.
 * @param schema - The schema for what to construct. As this is an {@link ImplicitFieldSchema}, a {@link FieldSchema}, {@link TreeNodeSchema} or {@link AllowedTypes} array can be provided.
 * @param data - The data used to construct the field content.
 * @remarks
 * When providing a {@link TreeNodeSchemaClass}, this is the same as invoking its constructor except that an unhydrated node can also be provided.
 * This function exists as a generalization that can be used in other cases as well,
 * such as when `undefined` might be allowed (for an optional field), or when the type should be inferred from the data when more than one type is possible.
 *
 * Like with {@link TreeNodeSchemaClass}'s constructor, its an error to provide an existing node to this API.
 * For that case, use {@link TreeBeta.clone}.
 */
function createFromInsertable(schema, data, context) {
    const cursor = cursorFromInsertable(schema, data, context);
    const result = cursor === undefined ? undefined : createFromCursor(schema, cursor);
    return result;
}
exports.createFromInsertable = createFromInsertable;
/**
 * Construct tree content that is compatible with the field defined by the provided `schema`.
 * @param schema - The schema for what to construct. As this is an {@link ImplicitFieldSchema}, a {@link FieldSchema}, {@link TreeNodeSchema} or {@link AllowedTypes} array can be provided.
 * @param data - The data used to construct the field content.
 * @remarks
 * When providing a {@link TreeNodeSchemaClass},
 * this is the same as invoking its constructor except that an unhydrated node can also be provided and the returned value is a cursor.
 * When `undefined` is provided (for an optional field), `undefined` is returned.
 */
function cursorFromInsertable(schema, data, context) {
    const storedSchema = (0, toStoredSchema_js_1.toStoredSchema)(schema);
    const schemaValidationPolicy = {
        policy: index_js_2.defaultSchemaPolicy,
        // TODO: optimize: This isn't the most efficient operation since its not cached, and has to convert all the schema.
        schema: storedSchema,
    };
    const mapTree = (0, toMapTree_js_1.mapTreeFromNodeData)(data, schema, context, schemaValidationPolicy);
    if (mapTree === undefined) {
        (0, internal_1.assert)(storedSchema.rootFieldSchema.kind === index_js_2.FieldKinds.optional.identifier, 0xa10 /* missing non-optional field */);
        return undefined;
    }
    return (0, index_js_2.cursorForMapTreeNode)(mapTree);
}
exports.cursorFromInsertable = cursorFromInsertable;
/**
 * Creates an unhydrated simple-tree field from a cursor in nodes mode.
 */
function createFromCursor(schema, cursor) {
    const mapTrees = cursor === undefined ? [] : [(0, index_js_2.mapTreeFromCursor)(cursor)];
    const context = (0, createContext_js_1.getUnhydratedContext)(schema);
    const flexSchema = context.flexContext.schema;
    const schemaValidationPolicy = {
        policy: {
            ...index_js_2.defaultSchemaPolicy,
            allowUnknownOptionalFields: (0, objectNode_js_1.createUnknownOptionalFieldPolicy)(schema),
        },
        schema: context.flexContext.schema,
    };
    const maybeError = (0, index_js_3.isFieldInSchema)(mapTrees, flexSchema.rootFieldSchema, schemaValidationPolicy);
    (0, toMapTree_js_1.inSchemaOrThrow)(maybeError);
    if (mapTrees.length === 0) {
        return undefined;
    }
    (0, internal_1.assert)(mapTrees.length === 1, 0xa11 /* unexpected field length */);
    // Length asserted above, so this is safe. This assert is done instead of checking for undefined after indexing to ensure a length greater than 1 also errors.
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    const mapTree = mapTrees[0];
    const mapTreeNode = index_js_1.UnhydratedFlexTreeNode.getOrCreate((0, createContext_js_1.getUnhydratedContext)(schema), mapTree);
    const result = (0, index_js_1.getOrCreateNodeFromInnerNode)(mapTreeNode);
    return result;
}
exports.createFromCursor = createFromCursor;
//# sourceMappingURL=create.js.map