"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.SchemaFactoryBeta = void 0;
const index_js_1 = require("../core/index.js");
/* eslint-enable unused-imports/no-unused-imports, import-x/no-duplicates */
const index_js_2 = require("../node-kinds/index.js");
const schemaFactory_js_1 = require("./schemaFactory.js");
const staged = (t) => {
    const annotatedType = (0, index_js_1.normalizeToAnnotatedAllowedType)(t);
    return {
        type: annotatedType.type,
        metadata: {
            ...annotatedType.metadata,
            stagedSchemaUpgrade: (0, index_js_1.createSchemaUpgrade)(),
        },
    };
};
const types = (t, metadata = {}) => {
    return index_js_1.AnnotatedAllowedTypesInternal.createMixed(t, metadata);
};
const schemaStaticsBeta = {
    staged,
    types,
    stagedRecursive: staged,
    typesRecursive: types,
};
/**
 * {@link SchemaFactory} with additional beta APIs.
 * @beta
 * @privateRemarks
 */
class SchemaFactoryBeta extends schemaFactory_js_1.SchemaFactory {
    constructor() {
        super(...arguments);
        /**
         * {@inheritDoc SchemaStaticsBeta.staged}
         */
        this.staged = schemaStaticsBeta.staged;
        /**
         * {@inheritDoc SchemaStaticsBeta.stagedRecursive}
         */
        this.stagedRecursive = schemaStaticsBeta.stagedRecursive;
        /**
         * {@inheritDoc SchemaStaticsBeta.types}
         */
        this.types = schemaStaticsBeta.types;
        /**
         * {@inheritDoc SchemaStaticsBeta.typesRecursive}
         */
        this.typesRecursive = schemaStaticsBeta.typesRecursive;
    }
    /**
     * Create a {@link SchemaFactory} with a {@link SchemaFactory.scope|scope} which is a combination of this factory's scope and the provided name.
     * @remarks
     * The main use-case for this is when creating a collection of related schema (for example using a function that creates multiple schema).
     * Creating such related schema using a sub-scope helps ensure they won't collide with other schema in the parent scope.
     */
    scopedFactory(name) {
        return new SchemaFactoryBeta((0, schemaFactory_js_1.scoped)(this, name));
    }
    /**
     * Define a {@link TreeNodeSchemaClass} for a {@link TreeObjectNode}.
     *
     * @param name - Unique identifier for this schema within this factory's scope.
     * @param fields - Schema for fields of the object node's schema. Defines what children can be placed under each key.
     * @param options - Additional options for the schema.
     */
    object(name, fields, options) {
        return (0, index_js_2.objectSchema)((0, schemaFactory_js_1.scoped)(this, name), fields, true, {
            ...schemaFactory_js_1.defaultSchemaFactoryObjectOptions,
            ...options,
        });
    }
    objectRecursive(name, t, options) {
        return this.object(name, t, options);
    }
    /**
     * {@link SchemaFactoryBeta.record} implementation.
     *
     * @privateRemarks
     * This should return {@link TreeNodeSchemaBoth}: see note on {@link SchemaFactory.map} implementation for details.
     */
    record(nameOrAllowedTypes, maybeAllowedTypes, options) {
        if (maybeAllowedTypes === undefined) {
            const nodeTypes = nameOrAllowedTypes;
            const fullName = (0, schemaFactory_js_1.structuralName)("Record", nodeTypes);
            return this.getStructuralType(fullName, nodeTypes, () => this.namedRecord(fullName, nameOrAllowedTypes, 
            /* customizable */ false, 
            /* implicitlyConstructable */ true));
        }
        const out = this.namedRecord(nameOrAllowedTypes, maybeAllowedTypes, 
        /* customizable */ true, 
        /* implicitlyConstructable */ true, options);
        return out;
    }
    /**
     * Define a {@link TreeNodeSchema} for a {@link (TreeRecordNode:interface)}.
     *
     * @param name - Unique identifier for this schema within this factory's scope.
     *
     * @remarks
     * This is not intended to be used directly, use the overload of `record` which takes a name instead.
     */
    namedRecord(name, allowedTypes, customizable, implicitlyConstructable, options) {
        return (0, index_js_2.recordSchema)({
            identifier: (0, schemaFactory_js_1.scoped)(this, name),
            info: allowedTypes,
            customizable,
            implicitlyConstructable,
            nodeOptions: options,
        });
    }
    /**
     * {@link SchemaFactoryBeta.(record:2)} except tweaked to work better for recursive types.
     * Use with {@link ValidateRecursiveSchema} for improved type safety.
     * @remarks
     * This version of `SchemaFactory.record` uses the same workarounds as {@link SchemaFactory.objectRecursive}.
     * See {@link ValidateRecursiveSchema} for additional information about using recursive schema.
     */
    // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
    recordRecursive(name, allowedTypes, options) {
        const RecordSchema = this.namedRecord(name, allowedTypes, 
        /* customizable */ true, 
        // Setting this to true seems to work ok currently, but not for other node kinds.
        // Supporting this could be fragile and might break other future changes, so it's being kept as false for now.
        /* implicitlyConstructable */ false, options);
        return RecordSchema;
    }
}
exports.SchemaFactoryBeta = SchemaFactoryBeta;
/**
 * {@inheritDoc SchemaStaticsBeta.staged}
 */
SchemaFactoryBeta.staged = schemaStaticsBeta.staged;
/**
 * {@inheritDoc SchemaStaticsBeta.stagedRecursive}
 */
SchemaFactoryBeta.stagedRecursive = schemaStaticsBeta.stagedRecursive;
/**
 * {@inheritDoc SchemaStaticsBeta.types}
 */
SchemaFactoryBeta.types = schemaStaticsBeta.types;
/**
 * {@inheritDoc SchemaStaticsBeta.typesRecursive}
 */
SchemaFactoryBeta.typesRecursive = schemaStaticsBeta.typesRecursive;
//# sourceMappingURL=schemaFactoryBeta.js.map