/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { BTree } from "@tylerbu/sorted-btree-es6";
import { createEmitter } from "../../events/index.js";
import { compareStrings } from "../../util/index.js";
import { storedEmptyFieldSchema, } from "./schema.js";
/**
 * Mutable TreeStoredSchema repository.
 */
export class TreeStoredSchemaRepository {
    /**
     * Copies in the provided schema. If `data` is an TreeStoredSchemaRepository, 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 = createEmitter();
        if (data === undefined) {
            this.rootFieldSchemaData = storedEmptyFieldSchema;
            this.nodeSchemaData = new BTree([], compareStrings);
        }
        else {
            if (data instanceof TreeStoredSchemaRepository) {
                this.rootFieldSchemaData = data.rootFieldSchema;
                this.nodeSchemaData = data.nodeSchemaData.clone();
            }
            else {
                this.rootFieldSchemaData = data.rootFieldSchema;
                this.nodeSchemaData = cloneNodeSchemaData(data.nodeSchema);
            }
        }
    }
    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;
    }
    apply(newSchema) {
        this.events.emit("beforeSchemaChange", newSchema);
        const clone = new TreeStoredSchemaRepository(newSchema);
        // In the future, we could use btree's delta functionality to do a more efficient update
        this.rootFieldSchemaData = clone.rootFieldSchemaData;
        this.nodeSchemaData = clone.nodeSchemaData;
        this.events.emit("afterSchemaChange", newSchema);
    }
    clone() {
        return new TreeStoredSchemaRepository(this);
    }
}
export function schemaDataIsEmpty(data) {
    return data.nodeSchema.size === 0;
}
function cloneNodeSchemaData(nodeSchema) {
    // Schema objects are immutable (unlike stored schema repositories), so this shallow copy is fine.
    const entries = [...nodeSchema.entries()];
    return new BTree(entries, compareStrings);
}
//# sourceMappingURL=storedSchemaRepository.js.map