"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.schemaDataIsEmpty = exports.InMemoryStoredSchemaRepository = void 0;
const sorted_btree_1 = __importDefault(require("sorted-btree"));
const events_1 = require("../../events");
const util_1 = require("../../util");
const schema_1 = require("./schema");
/**
 * StoredSchemaRepository for in memory use:
 * not hooked up to Fluid (does not create Fluid ops when editing).
 */
class InMemoryStoredSchemaRepository {
    /**
     * Copies in the provided schema. If `data` is an InMemoryStoredSchemaRepository, it will be cheap-cloned.
     * Otherwise, it will be deep-cloned.
     *
     * We might not want to store schema in maps long term, as we might want a way to reserve a
     * large space of schema IDs within a schema.
     * The way mapFields has been structured mitigates the need for this, but it still might be useful.
     *
     * (ex: someone using data as field identifiers might want to
     * reserve all fields identifiers starting with "foo." to have a specific schema).
     * Combined with support for such namespaces in the allowed sets in the schema objects,
     * that might provide a decent alternative to mapFields (which is a bit odd).
     */
    constructor(data) {
        this.events = (0, events_1.createEmitter)();
        this.rootFieldSchemaData = schema_1.storedEmptyFieldSchema;
        this.nodeSchemaData = new sorted_btree_1.default([], util_1.compareStrings);
        if (data !== undefined) {
            this.cloneData(data);
        }
    }
    on(eventName, listener) {
        return this.events.on(eventName, listener);
    }
    get nodeSchema() {
        // Btree implements iterator, but not in a type-safe way
        return this.nodeSchemaData;
    }
    get rootFieldSchema() {
        return this.rootFieldSchemaData;
    }
    update(newSchema) {
        this.events.emit("beforeSchemaChange", newSchema);
        // In the future, we could use btree's delta functionality to do a more efficient update
        this.cloneData(newSchema);
        this.events.emit("afterSchemaChange", newSchema);
    }
    cloneData(data) {
        if (data instanceof InMemoryStoredSchemaRepository) {
            this.rootFieldSchemaData = data.rootFieldSchema;
            this.nodeSchemaData = data.nodeSchemaData.clone();
        }
        else {
            this.rootFieldSchemaData = cloneFieldSchemaData(data.rootFieldSchema);
            this.nodeSchemaData = cloneNodeSchemaData(data.nodeSchema);
        }
    }
}
exports.InMemoryStoredSchemaRepository = InMemoryStoredSchemaRepository;
function schemaDataIsEmpty(data) {
    return data.nodeSchema.size === 0;
}
exports.schemaDataIsEmpty = schemaDataIsEmpty;
function cloneNodeSchemaData(nodeSchema) {
    const entries = [];
    for (const [name, schema] of nodeSchema.entries()) {
        entries.push([
            name,
            {
                mapFields: schema.mapFields === undefined
                    ? undefined
                    : cloneFieldSchemaData(schema.mapFields),
                objectNodeFields: new Map(schema.objectNodeFields),
                leafValue: schema.leafValue,
            },
        ]);
    }
    return new sorted_btree_1.default(entries, util_1.compareStrings);
}
function cloneFieldSchemaData(fieldSchema) {
    return {
        kind: fieldSchema.kind,
        types: fieldSchema.types === undefined ? undefined : new Set(fieldSchema.types),
    };
}
//# sourceMappingURL=storedSchemaRepository.js.map