/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { assert } from "@fluidframework/common-utils";
import { FieldKinds } from "../default-field-kinds";
import { normalizeFlexList } from "./flexList";
import { objectToMapTyped } from "./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
 */
export class TreeSchema {
    constructor(builder, name, info) {
        this.builder = builder;
        this.info = info;
        this.name = name;
        this.structFieldsObject = normalizeStructFields(this.info.structFields);
        this.structFields = objectToMapTyped(this.structFieldsObject);
        this.mapFields = this.info.mapFields;
        this.leafValue = this.info.leafValue;
    }
}
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;
    }
    assert(t instanceof FieldSchema, 0x6ae /* invalid FieldSchema */);
    return t;
}
/**
 * Allow any node (as long as it meets the schema for its own type).
 * @alpha
 */
export const Any = "Any";
/**
 * Checks if an {@link AllowedTypes} is {@link (Any:type)}.
 * @alpha
 */
export function allowedTypesIsAny(t) {
    return t.length === 1 && t[0] === Any;
}
/**
 * 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
 */
export class FieldSchema {
    constructor(kind, allowedTypes) {
        this.kind = kind;
        this.allowedTypes = allowedTypes;
    }
    get types() {
        return allowedTypesToTypeSet(this.allowedTypes);
    }
}
/**
 * Schema for a field which must always be empty.
 */
FieldSchema.empty = new FieldSchema(FieldKinds.forbidden, []);
// TODO: maybe remove the need for this here? Just use AllowedTypes in view schema?
/**
 * Convert {@link AllowedTypes} to {@link TreeTypeSet}.
 * @alpha
 */
export function allowedTypesToTypeSet(t) {
    if (allowedTypesIsAny(t)) {
        return undefined;
    }
    const list = normalizeFlexList(t);
    const names = list.map((f) => f().name);
    return new Set(names);
}
//# sourceMappingURL=typedTreeSchema.js.map