/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import type { FieldKey } from "../schema-stored/index.js";
import type * as Delta from "./delta.js";
import type { ProtoNodes } from "./delta.js";
import type { DetachedFieldIndex } from "./detachedFieldIndex.js";
import type { NodeIndex, PlaceIndex, Range } from "./pathTree.js";
import type { RevisionTag } from "../index.js";
/**
 * Implementation notes:
 *
 * The visit is organized into four phases:
 * 1. a detach pass
 * 2. root transfers
 * 3. an attach pass
 * 4. root destructions
 *
 * The core idea is that before content can be attached, it must first exist and be in a detached field.
 * The detach pass is therefore responsible for making sure that all roots that needs to be attached during the
 * attach pass are detached.
 * In practice, this means the detach pass must:
 * - Create all subtrees that need to be created
 * - Detach all moved nodes
 *
 * In addition to that, the detach pass also detaches nodes that need removing, with the exception of nodes that get
 * replaced. The reason for this exception is that we need to be able to communicate replaces as atomic operations.
 * In order to do that, we need to wait until we are sure that the content to attach is available as a detached root.
 * Replaces are therefore handled during the attach pass.
 * Note that this could theoretically lead to a situation where, in the attach pass, one replace wants to attach
 * a node that has yet to be detached by another replace. This does not occur in practice because we do not support
 * editing operations that would lead to this situation.
 *
 * While the detach pass ensures that nodes to be attached are in a detached state, it does not guarantee that they
 * reside in the correct detach field. That is the responsibility of the root transfers phase.
 *
 * The attach phase carries out attaches and replaces.
 *
 * After the attach phase, roots destruction is carried out.
 * This needs to happen last to allow modifications to detached roots to be applied before they are destroyed.
 *
 * The details of the delta visit algorithm can impact how/when events are emitted by the objects that own the visitors.
 * For example, as of 2024-03-27, the subtreecChanged event of an AnchorNode is emitted when exiting a node during a
 * delta visit, and thus the two-pass nature of the algorithm means the event fires twice for any given change.
 * This two-pass nature also means that the event may fire at a time where no change is visible in the tree. E.g.,
 * if a node is being replaced, when the event fires during the detach pass no change in the tree has happened so the
 * listener won't see any; then when it fires during the attach pass, the change will be visible in the event listener.
 */
/**
 * Crawls the given `delta`, calling `visitor`'s callback for each change encountered.
 * Each successive call to the visitor callbacks assumes that the change described by earlier calls have been applied
 * to the document tree. For example, for a change that removes the first and third node of a field, the visitor calls
 * will first call detach with a range from indices 0 to 1 then call detach with a range from indices 1 to 2.
 *
 * @param delta - The delta to be crawled.
 * @param visitor - The object to notify of the changes encountered.
 * @param detachedFieldIndex - Index responsible for keeping track of the existing detached fields.
 * @param latestRevision - The latest revision tag associated with this delta.
 */
export declare function visitDelta(delta: Delta.Root, visitor: DeltaVisitor, detachedFieldIndex: DetachedFieldIndex, latestRevision: RevisionTag | undefined): void;
/**
 * Visitor for changes in a delta.
 * Must be freed after use.
 */
export interface DeltaVisitor {
    /**
     * Frees/releases the visitor.
     *
     * Must be called once the visitor finished traversing the delta for a couple of reasons:
     *
     * 1. Some visitors, such as those from forests, are put into a special mode while they have a visitor, forbidding some actions (like making more visitors).
     *
     * 2. Some visitors, such as those from an anchorSet, defer some events for batching purposes until the visitor is freed.
     */
    free(): void;
    /**
     * Creates nodes for the given content in a new detached field.
     * @param content - The content to create.
     * @param destination - The key for a new detached field.
     * A field with this key must not already exist.
     */
    create(content: ProtoNodes, destination: FieldKey): void;
    /**
     * Recursively destroys the given detached field and all of the nodes within it.
     * @param detachedField - The key for the detached field to destroy.
     * @param count - The number of nodes being destroyed.
     * Expected to match the number of nodes in the detached field being destroyed.
     */
    destroy(detachedField: FieldKey, count: number): void;
    /**
     * Transfers all the nodes from a detached field to the current field.
     * @param source - The detached field to transfer the nodes from.
     * @param count - The number of nodes being attached.
     * Expected to match the number of nodes in the source detached field.
     * @param destination - The index at which to attach the nodes.
     */
    attach(source: FieldKey, count: number, destination: PlaceIndex): void;
    /**
     * Transfers a range of nodes from the current field to a new detached field.
     * @param source - The bounds of the range of nodes to detach.
     * @param destination - The key for a new detached field.
     * A field with this key must not already exist.
     */
    detach(source: Range, destination: FieldKey): void;
    /**
     * Replaces a range of nodes in the current field by transferring them out to a new detached field
     * and transferring in all the nodes from an existing detached field in their place.
     * The number of nodes being detached must match the number of nodes being attached.
     * @param newContentSource - The detached field to transfer the new nodes from.
     * @param range - The bounds of the range of nodes to replace.
     * @param oldContentDestination - The key for a new detached field to transfer the old nodes to.
     */
    replace(newContentSource: FieldKey, range: Range, oldContentDestination: FieldKey): void;
    /**
     * Tells the visitor that it should update its "current location" to be the Node at the specified index
     * within the Field that is the current "current location".
     * Future calls to methods of {@link DeltaVisitor} will assume that's the location where their effects are happening.
     * @param index - The index (within the Field) of the node that should become the new "current location".
     *
     * @remarks This should only be called when the "current location" is a Field.
     */
    enterNode(index: NodeIndex): void;
    /**
     * Tells the visitor that it should update its "current location" to be the Field which contains the Node
     * that is the current "current location".
     * Future calls to methods of {@link DeltaVisitor} will assume that's the location where their effects are happening.
     * @param index - The index (within its Field) of the node that is being exited.
     *
     * @remarks This should only be called when the "current location" is a Node.
     */
    exitNode(index: NodeIndex): void;
    /**
     * Tells the visitor that it should update its "current location" to be the Field with the specified key,
     * within the Node that is the current "current location".
     * Future calls to methods of {@link DeltaVisitor} will assume that's the location where their effects are happening.
     * @param key - The key of the field that should become the new "current location".
     *
     * @remarks This should only be called when the "current location" is a Node.
     */
    enterField(key: FieldKey): void;
    /**
     * Tells the visitor that it should update its "current location" to be the Node which contains the Field
     * that is the current "current location".
     * Future calls to methods of {@link DeltaVisitor} will assume that's the location where their effects are happening.
     * @param key - The key of the field that is being exited.
     *
     * @remarks This should only be called when the "current location" is a Field.
     */
    exitField(key: FieldKey): void;
}
//# sourceMappingURL=visitDelta.d.ts.map