/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { keyFromSymbol, treeSchema, ValueSchema, } from "../../../core";
import { brand } from "../../../util";
import { forbidden } from "../../defaultFieldKinds";
import { namedTreeSchema } from "../../viewSchemaUtil";
/**
 * Builds a TreeSchema with the type information also captured in the
 * typescript type to allow for deriving schema aware APIs.
 *
 * @remarks
 * The name is passed is separate instead of part of the builder to the caller does not have to
 * do "as const" after the name for its type to be captured properly.
 *
 * @alpha
 */
export function typedTreeSchema(name, t) {
    var _a, _b, _c, _d, _e, _f, _g, _h;
    const data = {
        localFields: t.local,
        globalFields: (_b = (_a = t.global) === null || _a === void 0 ? void 0 : _a.map((key) => keyFromSymbol(typeof key === "symbol" ? key : key.name))) !== null && _b !== void 0 ? _b : [],
        extraLocalFields: (_c = t.extraLocalFields) !== null && _c !== void 0 ? _c : emptyField,
        extraGlobalFields: t.extraGlobalFields,
        value: t.value,
    };
    // TreeInfoFromBuilder<T, TName>
    const typeInfo = {
        name,
        local: (_d = t.local) !== null && _d !== void 0 ? _d : {},
        global: extractNames((_e = t.global) !== null && _e !== void 0 ? _e : []),
        extraLocalFields: (_f = t.extraLocalFields) !== null && _f !== void 0 ? _f : emptyField,
        extraGlobalFields: (_g = t.extraGlobalFields) !== null && _g !== void 0 ? _g : false,
        value: (_h = t.value) !== null && _h !== void 0 ? _h : ValueSchema.Nothing,
    };
    return Object.assign(Object.assign({ name: brand(name) }, treeSchema(data)), { typeInfo });
}
/**
 * Builds a FieldSchema with the type information also captured in the
 * typescript type to allow for deriving schema aware APIs.
 *
 * @remarks
 * The typing here explicitly forbids passing no types: no types would make a field that didn't allow anything.
 * While the underlying system does support such fields (which can be useful if planning to modify their schema later),
 * usually what is instead desired is a field which allows any child type.
 * For that see {@link TypedSchema#fieldUnrestricted}.
 *
 * @alpha
 */
export function typedFieldSchema(kind, ...typeArray) {
    const types = nameSet(...typeArray);
    return { kind, types };
}
/**
 * Builds a FieldSchema with the type information also captured in the
 * typescript type to allow for deriving schema aware APIs.
 *
 * For fields with unrestricted polymorphism (meaning all child types are allowed).
 * @alpha
 */
export function unrestrictedFieldSchema(kind) {
    return { kind };
}
function extractNames(items) {
    return items.map((item) => typeof item === "object" ? item.name : item);
}
export function nameSetSimple(...names) {
    return new Set(names);
}
/**
 * Gets a set of names from a list of named objects or names.
 * @alpha
 */
export function nameSet(...names) {
    return new Set(extractNames(names));
}
/**
 * Builds a TreeSchema with the type information also captured in the
 * typescript type to allow for deriving schema aware APIs.
 */
export function typedTreeSchemaFromInfo(t) {
    return namedTreeSchema(Object.assign(Object.assign({}, t), { name: brand(t.name) }));
}
/**
 * Schema for a field which must always be empty.
 * @alpha
 */
export const emptyField = unrestrictedFieldSchema(forbidden);
//# sourceMappingURL=typedSchema.js.map