"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.allowedTypesToTypeSet = exports.FieldSchema = exports.allowedTypesIsAny = exports.Any = exports.TreeSchema = void 0;
const common_utils_1 = require("@fluidframework/common-utils");
const default_field_kinds_1 = require("../default-field-kinds");
const flexList_1 = require("./flexList");
const typeUtils_1 = require("./typeUtils");
/**
 * T must extend TreeSchemaSpecification.
 * This can not be enforced using TypeScript since doing so breaks recursive type support.
 * See note on SchemaBuilder.fieldRecursive.
 * @alpha
 */
class TreeSchema {
    constructor(builder, name, info) {
        this.builder = builder;
        this.info = info;
        this.name = name;
        this.structFieldsObject = normalizeStructFields(this.info.structFields);
        this.structFields = (0, typeUtils_1.objectToMapTyped)(this.structFieldsObject);
        this.mapFields = this.info.mapFields;
        this.leafValue = this.info.leafValue;
    }
}
exports.TreeSchema = TreeSchema;
function normalizeStructFields(fields) {
    if (fields === undefined) {
        return {};
    }
    const out = {};
    // eslint-disable-next-line no-restricted-syntax
    for (const key in fields) {
        if (Object.prototype.hasOwnProperty.call(fields, key)) {
            const element = fields[key];
            out[key] = normalizeField(element);
        }
    }
    return out;
}
function normalizeField(t) {
    if (t === undefined) {
        return FieldSchema.empty;
    }
    (0, common_utils_1.assert)(t instanceof FieldSchema, 0x6ae /* invalid FieldSchema */);
    return t;
}
/**
 * Allow any node (as long as it meets the schema for its own type).
 * @alpha
 */
exports.Any = "Any";
/**
 * Checks if an {@link AllowedTypes} is {@link (Any:type)}.
 * @alpha
 */
function allowedTypesIsAny(t) {
    return t.length === 1 && t[0] === exports.Any;
}
exports.allowedTypesIsAny = allowedTypesIsAny;
/**
 * All policy for a specific field,
 * including functionality that does not have to be kept consistent across versions or deterministic.
 *
 * This can include policy for how to use this schema for "view" purposes, and well as how to expose editing APIs.
 * @sealed @alpha
 */
class FieldSchema {
    constructor(kind, allowedTypes) {
        this.kind = kind;
        this.allowedTypes = allowedTypes;
    }
    get types() {
        return allowedTypesToTypeSet(this.allowedTypes);
    }
}
exports.FieldSchema = FieldSchema;
/**
 * Schema for a field which must always be empty.
 */
FieldSchema.empty = new FieldSchema(default_field_kinds_1.FieldKinds.forbidden, []);
// TODO: maybe remove the need for this here? Just use AllowedTypes in view schema?
/**
 * Convert {@link AllowedTypes} to {@link TreeTypeSet}.
 * @alpha
 */
function allowedTypesToTypeSet(t) {
    if (allowedTypesIsAny(t)) {
        return undefined;
    }
    const list = (0, flexList_1.normalizeFlexList)(t);
    const names = list.map((f) => f().name);
    return new Set(names);
}
exports.allowedTypesToTypeSet = allowedTypesToTypeSet;
//# sourceMappingURL=typedTreeSchema.js.map