/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { unreachableCase } from "@fluidframework/core-utils/internal";
import { AnchorSet, tagChange, visitDelta, } from "../core/index.js";
import { chunkTree, defaultChunkPolicy, intoDelta, relevantRemovedRoots, updateRefreshers as updateDataChangeRefreshers, } from "../feature-libraries/index.js";
import { disposeSymbol } from "../util/index.js";
import { updateRefreshers } from "./sharedTreeChangeFamily.js";
export class SharedTreeReadonlyChangeEnricher {
    /**
     * @param forest - The state based on which to enrich changes.
     * Exclusively owned by the constructed instance.
     * @param schema - The schema that corresponds to the forest.
     * @param removedRoots - The set of removed roots based on which to enrich changes.
     * Exclusively owned by the constructed instance.
     */
    constructor(forest, schema, removedRoots) {
        this.forest = forest;
        this.schema = schema;
        this.removedRoots = removedRoots;
        this.getDetachedRoot = (id) => {
            const root = this.removedRoots.tryGetEntry(id);
            if (root !== undefined) {
                const cursor = this.forest.getCursorAboveDetachedFields();
                const parentField = this.removedRoots.toFieldKey(root);
                cursor.enterField(parentField);
                cursor.enterNode(0);
                return chunkTree(cursor, defaultChunkPolicy);
            }
            return undefined;
        };
    }
    fork() {
        return new SharedTreeMutableChangeEnricher(this.forest.clone(this.schema, new AnchorSet()), this.schema, this.removedRoots.clone());
    }
    updateChangeEnrichments(change) {
        return updateRefreshers(change, this.getDetachedRoot, relevantRemovedRoots, updateDataChangeRefreshers);
    }
}
export class SharedTreeMutableChangeEnricher extends SharedTreeReadonlyChangeEnricher {
    applyTipChange(change, revision) {
        for (const dataOrSchemaChange of change.changes) {
            const type = dataOrSchemaChange.type;
            switch (type) {
                case "data": {
                    const delta = intoDelta(tagChange(dataOrSchemaChange.innerChange, revision));
                    const visitor = this.forest.acquireVisitor();
                    visitDelta(delta, visitor, this.removedRoots);
                    visitor.free();
                    break;
                }
                case "schema":
                    // This enricher doesn't need to maintain schema information.
                    // Note that the refreshers being generated through `updateChangeEnrichments` will be encoded using
                    // the schema that was used in the input context of the data changeset these refreshers are on.
                    // See the encoding logic in SharedTreeCore for details.
                    break;
                default:
                    unreachableCase(type);
            }
        }
    }
    [disposeSymbol]() {
        // TODO: in the future, forest and/or its AnchorSet may require disposal.
    }
}
//# sourceMappingURL=sharedTreeChangeEnricher.js.map