/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import BTree from "sorted-btree";
import { createEmitter } from "../../events";
import { compareStrings } from "../../util";
import { storedEmptyFieldSchema, } from "./schema";
/**
 * StoredSchemaRepository for in memory use:
 * not hooked up to Fluid (does not create Fluid ops when editing).
 */
export 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 = createEmitter();
        this.rootFieldSchemaData = storedEmptyFieldSchema;
        this.nodeSchemaData = new BTree([], 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);
        }
    }
}
export function schemaDataIsEmpty(data) {
    return data.nodeSchema.size === 0;
}
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 BTree(entries, compareStrings);
}
function cloneFieldSchemaData(fieldSchema) {
    return {
        kind: fieldSchema.kind,
        types: fieldSchema.types === undefined ? undefined : new Set(fieldSchema.types),
    };
}
//# sourceMappingURL=storedSchemaRepository.js.map