"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.walkAllowedTypes = exports.walkFieldSchema = exports.walkNodeSchema = exports.TreeViewConfiguration = void 0;
const schemaTypes_js_1 = require("./schemaTypes.js");
const toFlexSchema_js_1 = require("./toFlexSchema.js");
const leafNodeSchema_js_1 = require("./leafNodeSchema.js");
const internal_1 = require("@fluidframework/core-utils/internal");
const objectNode_js_1 = require("./objectNode.js");
const schemaFactory_js_1 = require("./schemaFactory.js");
const defaultTreeConfigurationOptions = {
    enableSchemaValidation: false,
};
/**
 * Configuration for {@link ITree.viewWith}.
 * @sealed @public
 */
class TreeViewConfiguration {
    /**
     * @param props - Property bag of configuration options.
     */
    constructor(props) {
        const config = { ...defaultTreeConfigurationOptions, ...props };
        this.schema = config.schema;
        this.enableSchemaValidation = config.enableSchemaValidation;
        // Ensure all reachable schema are marked as most derived.
        // This ensures if multiple schema extending the same schema factory generated class are present (or have been constructed, or get constructed in the future),
        // an error is reported.
        walkFieldSchema(config.schema, schemaFactory_js_1.markSchemaMostDerived);
        // Eagerly perform this conversion to surface errors sooner.
        (0, toFlexSchema_js_1.toFlexSchema)(config.schema);
    }
}
exports.TreeViewConfiguration = TreeViewConfiguration;
function walkNodeSchema(schema, visitor, visitedSet) {
    if (visitedSet.has(schema)) {
        return;
    }
    visitedSet.add(schema);
    if (schema instanceof leafNodeSchema_js_1.LeafNodeSchema) {
        // nothing to do
    }
    else if ((0, objectNode_js_1.isObjectNodeSchema)(schema)) {
        for (const field of schema.fields.values()) {
            walkAllowedTypes(field.allowedTypeSet, visitor, visitedSet);
        }
    }
    else {
        (0, internal_1.assert)(schema.kind === schemaTypes_js_1.NodeKind.Array || schema.kind === schemaTypes_js_1.NodeKind.Map, 0x9b3 /* invalid schema */);
        const childTypes = schema.info;
        walkFieldSchema(childTypes, visitor, visitedSet);
    }
    // This visit is done at the end so the traversal order is most inner types first.
    // This was picked since when fixing errors,
    // working from the inner types out to the types that use them will probably go better than the reverse.
    // This does not however ensure all types referenced by a type are visited before it, since in recursive cases thats impossible.
    visitor(schema);
}
exports.walkNodeSchema = walkNodeSchema;
function walkFieldSchema(schema, visitor, visitedSet = new Set()) {
    walkAllowedTypes((0, schemaTypes_js_1.normalizeFieldSchema)(schema).allowedTypeSet, visitor, visitedSet);
}
exports.walkFieldSchema = walkFieldSchema;
function walkAllowedTypes(allowedTypes, visitor, visitedSet) {
    for (const childType of allowedTypes) {
        walkNodeSchema(childType, visitor, visitedSet);
    }
}
exports.walkAllowedTypes = walkAllowedTypes;
//# sourceMappingURL=tree.js.map