/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import type { Listenable } from "@fluidframework/core-interfaces/internal";
import type { IIdCompressor } from "@fluidframework/id-compressor";
import { type ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
import { type Anchor, type AnchorLocator, type AnchorNode, type AnchorSetRootEvents, type ChangeFamily, type CommitMetadata, type DetachedFieldIndex, type IEditableForest, type IForestSubscription, type JsonableTree, type RevisionTag, type RevisionTagCodec, type TreeStoredSchema, TreeStoredSchemaRepository, type TreeStoredSchemaSubscription, type RevertibleAlphaFactory, type GraphCommit } from "../core/index.js";
import { type FieldBatchCodec, type TreeCompressionStrategy } from "../feature-libraries/index.js";
import { SharedTreeBranch, type SharedTreeBranchChange, type Transactor } from "../shared-tree-core/index.js";
import { Breakable, disposeSymbol, type WithBreakable } from "../util/index.js";
import type { SharedTreeChange } from "./sharedTreeChangeTypes.js";
import type { ISharedTreeEditor, SharedTreeEditBuilder } from "./sharedTreeEditBuilder.js";
import type { IDisposable } from "@fluidframework/core-interfaces";
import type { ImplicitFieldSchema, ReadSchema, TreeView, TreeViewConfiguration, UnsafeUnknownSchema, ViewableTree } from "../simple-tree/index.js";
import { SchematizingSimpleTreeView } from "./schematizingTreeView.js";
/**
 * Events for {@link ITreeCheckout}.
 */
export interface CheckoutEvents {
    /**
     * The view is currently in a consistent state, but a batch of changes is about to be processed.
     * @remarks Once this event fires, it is not safe to access the FlexTree, Forest and AnchorSet again until the corresponding {@link CheckoutEvents.afterBatch} fires.
     * Every call to `beforeBatch` will be followed by a corresponding call to `afterBatch` (before any more calls to `beforeBatch`).
     * @param change - The {@link SharedTreeBranchChange | change} to the checkout's active branch that is about to be processed.
     * May be empty if the changes were produced by e.g. a rebase or the initial loading of the document.
     */
    beforeBatch(change: SharedTreeBranchChange<SharedTreeChange>): void;
    /**
     * A batch of changes has finished processing and the view is in a consistent state.
     * @remarks It is once again safe to access the FlexTree, Forest and AnchorSet.
     *
     * While every call to `beforeBatch` will be followed by a corresponding call to `afterBatch`, the converse is not true.
     * This event may be fired without a preceding `beforeBatch` event if the checkout's branch and forest were directly updated via e.g. a summary load rather than via normal application of changes.
     * @remarks
     * This is mainly useful for knowing when to do followup work scheduled during events from Anchors.
     */
    afterBatch(): void;
    /**
     * Fired when a change is made to the branch. Includes data about the change that is made which listeners
     * can use to filter on changes they care about e.g. local vs remote changes.
     *
     * @param data - information about the change
     * @param getRevertible - a function provided that allows users to get a revertible for the change. If not provided,
     * this change is not revertible.
     */
    changed(data: CommitMetadata, getRevertible?: RevertibleAlphaFactory): void;
    /**
     * Fired when a new branch is created from this checkout.
     */
    fork(branch: ITreeCheckout): void;
    /**
     * Fired when the checkout is disposed.
     */
    dispose(): void;
}
/**
 * A "version control"-style branch of a SharedTree.
 * @remarks Branches may be used to coordinate edits to a SharedTree, e.g. via merge and rebase operations.
 * Changes applied to a branch of a branch only apply to that branch and are isolated from other branches.
 * Changes may be synchronized across branches via merge and rebase operations provided on the branch object.
 * @alpha @sealed
 */
export interface BranchableTree extends ViewableTree {
    /**
     * Spawn a new branch which is based off of the current state of this branch.
     * Any mutations of the new branch will not apply to this branch until the new branch is merged back into this branch via `merge()`.
     */
    branch(): TreeBranchFork;
    /**
     * Apply all the new changes on the given branch to this branch.
     * @param view - a branch which was created by a call to `branch()`.
     * It is automatically disposed after the merge completes.
     * @remarks All ongoing transactions (if any) in `branch` will be committed before the merge.
     * A "changed" event and a corresponding {@link Revertible} will be emitted on this branch for each new change merged from 'branch'.
     */
    merge(branch: TreeBranchFork): void;
    /**
     * Apply all the new changes on the given branch to this branch.
     * @param branch - a branch which was created by a call to `branch()`.
     * @param disposeMerged - whether or not to dispose `branch` after the merge completes.
     * @remarks All ongoing transactions (if any) in `branch` will be committed before the merge.
     */
    merge(branch: TreeBranchFork, disposeMerged: boolean): void;
    /**
     * Rebase the given branch onto this branch.
     * @param branch - a branch which was created by a call to `branch()`. It is modified by this operation.
     */
    rebase(branch: TreeBranchFork): void;
}
/**
 * A {@link BranchableTree | branch} of a SharedTree that has merged from another branch.
 * @remarks This branch should be disposed when it is no longer needed in order to free resources.
 * @alpha @sealed
 */
export interface TreeBranchFork extends BranchableTree, IDisposable {
    /**
     * Rebase the changes that have been applied to this branch over all the new changes in the given branch.
     * @param branch - Either the root branch or a branch that was created by a call to `branch()`. It is not modified by this operation.
     */
    rebaseOnto(branch: BranchableTree): void;
}
/**
 * Provides a means for interacting with a SharedTree.
 * This includes reading data from the tree and running transactions to mutate the tree.
 * @remarks This interface should not have any implementations other than those provided by the SharedTree package libraries.
 * @privateRemarks
 * API for interacting with a {@link SharedTreeBranch}.
 * Implementations of this interface must implement the {@link branchKey} property.
 */
export interface ITreeCheckout extends AnchorLocator, ViewableTree, WithBreakable {
    /**
     * Read and Write access for schema stored in the document.
     *
     * These APIs are temporary and will be replaced with different abstractions (View Schema based) in a different place later.
     *
     * TODO:
     * Editing of this should be moved into transactions with the rest of tree editing to they can be intermixed.
     * This will be done after the relations between views, branches and Indexes are figured out.
     *
     * TODO:
     * Public APIs for dealing with schema should be in terms of View Schema, and schema update policies.
     * The actual stored schema should be hidden (or ar least not be the most prominent way to interact with schema).
     *
     * TODO:
     * Something should ensure the document contents are always in schema.
     */
    readonly storedSchema: TreeStoredSchemaSubscription;
    /**
     * Current contents.
     * Updated by edits (local and remote).
     * Use `editor` to create a local edit.
     */
    readonly forest: IForestSubscription;
    /**
     * Used to edit the state of the tree. Edits will be immediately applied locally to the tree.
     * If there is no transaction currently ongoing, then the edits will be submitted to Fluid immediately as well.
     */
    readonly editor: ISharedTreeEditor;
    /**
     * A collection of functions for managing transactions.
     */
    readonly transaction: Transactor;
    branch(): ITreeCheckoutFork;
    merge(checkout: ITreeCheckoutFork): void;
    merge(checkout: ITreeCheckoutFork, disposeMerged: boolean): void;
    rebase(checkout: ITreeCheckoutFork): void;
    /**
     * Replaces all schema with the provided schema.
     * Can over-write preexisting schema, and removes unmentioned schema.
     */
    updateSchema(newSchema: TreeStoredSchema): void;
    /**
     * Events about this view.
     */
    readonly events: Listenable<CheckoutEvents>;
    /**
     * Events about the root of the tree in this view.
     */
    readonly rootEvents: Listenable<AnchorSetRootEvents>;
    /**
     * Returns a JsonableTree for each tree that was removed from (and not restored to) the document.
     * This list is guaranteed to contain all nodes that are recoverable through undo/redo on this checkout.
     * The list may also contain additional nodes.
     *
     * This is only intended for use in testing and exceptional code paths: it is not performant.
     */
    getRemovedRoots(): [string | number | undefined, number, JsonableTree][];
}
/**
 * Creates a {@link TreeCheckout}.
 * @param args - an object containing optional components that will be used to build the view.
 * Any components not provided will be created by default.
 * @remarks This does not create a {@link SharedTree}, but rather a view with the minimal state
 * and functionality required to implement {@link ITreeCheckout}.
 */
export declare function createTreeCheckout(idCompressor: IIdCompressor, mintRevisionTag: () => RevisionTag, revisionTagCodec: RevisionTagCodec, args?: {
    branch?: SharedTreeBranch<SharedTreeEditBuilder, SharedTreeChange>;
    changeFamily?: ChangeFamily<SharedTreeEditBuilder, SharedTreeChange>;
    schema?: TreeStoredSchemaRepository;
    forest?: IEditableForest;
    fieldBatchCodec?: FieldBatchCodec;
    removedRoots?: DetachedFieldIndex;
    chunkCompressionStrategy?: TreeCompressionStrategy;
    logger?: ITelemetryLoggerExt;
    breaker?: Breakable;
    disposeForksAfterTransaction?: boolean;
}): TreeCheckout;
/**
 * Branch (like in a version control system) of SharedTree.
 *
 * {@link ITreeCheckout} that has forked off of the main trunk/branch.
 */
export interface ITreeCheckoutFork extends ITreeCheckout {
    rebaseOnto(view: ITreeCheckout): void;
}
/**
 * Metrics derived from a revert operation.
 *
 * @see {@link TreeCheckout.revertRevertible}.
 */
export interface RevertMetrics {
    /**
     * The age of the revertible commit relative to the head of the branch to which the reversion will be applied.
     */
    readonly age: number;
}
/**
 * An implementation of {@link ITreeCheckoutFork}.
 */
export declare class TreeCheckout implements ITreeCheckoutFork {
    #private;
    /** True if and only if this checkout is for a forked branch and not the "main branch" of the tree. */
    readonly isBranch: boolean;
    private readonly changeFamily;
    readonly storedSchema: TreeStoredSchemaRepository;
    readonly forest: IEditableForest;
    private readonly mintRevisionTag;
    private readonly revisionTagCodec;
    private readonly idCompressor;
    private removedRoots;
    /** Optional logger for telemetry. */
    private readonly logger?;
    readonly breaker: Breakable;
    private readonly disposeForksAfterTransaction;
    disposed: boolean;
    private readonly editLock;
    private readonly views;
    /**
     * Set of revertibles maintained for automatic disposal
     */
    private readonly revertibles;
    /**
     * Each branch's head commit corresponds to a revertible commit.
     * Maintaining a whole branch ensures the commit graph is not pruned in a way that would prevent the commit from
     * being reverted.
     */
    private readonly revertibleCommitBranches;
    /**
     * The name of the telemetry event logged for calls to {@link TreeCheckout.revertRevertible}.
     * @privateRemarks Exposed for testing purposes.
     */
    static readonly revertTelemetryEventName = "RevertRevertible";
    events: Listenable<CheckoutEvents>;
    constructor(branch: SharedTreeBranch<SharedTreeEditBuilder, SharedTreeChange>, 
    /** True if and only if this checkout is for a forked branch and not the "main branch" of the tree. */
    isBranch: boolean, changeFamily: ChangeFamily<SharedTreeEditBuilder, SharedTreeChange>, storedSchema: TreeStoredSchemaRepository, forest: IEditableForest, mintRevisionTag: () => RevisionTag, revisionTagCodec: RevisionTagCodec, idCompressor: IIdCompressor, removedRoots?: DetachedFieldIndex, 
    /** Optional logger for telemetry. */
    logger?: ITelemetryLoggerExt | undefined, breaker?: Breakable, disposeForksAfterTransaction?: boolean);
    private readonly onAfterChange;
    private readonly onAncestryTrimmed;
    private withCombinedVisitor;
    private checkNotDisposed;
    /**
     * Creates a {@link RevertibleAlpha} object that can undo a specific change in the tree's history.
     * Revision must exist in the given {@link TreeCheckout}'s branch.
     *
     * @param revision - The revision tag identifying the change to be made revertible.
     * @param kind - The {@link CommitKind} that produced this revertible (e.g., Default, Undo, Redo).
     * @param checkout - The {@link TreeCheckout} instance this revertible belongs to.
     * @param onRevertibleDisposed - Callback function that will be called when the revertible is disposed.
     * @returns - {@link RevertibleAlpha}
     */
    private createRevertible;
    viewWith<TRoot extends ImplicitFieldSchema | UnsafeUnknownSchema>(config: TreeViewConfiguration<ReadSchema<TRoot>>): SchematizingSimpleTreeView<TRoot>;
    viewWith<TRoot extends ImplicitFieldSchema>(config: TreeViewConfiguration<TRoot>): TreeView<TRoot>;
    get rootEvents(): Listenable<AnchorSetRootEvents>;
    get editor(): ISharedTreeEditor;
    locate(anchor: Anchor): AnchorNode | undefined;
    get transaction(): Transactor;
    branch(): TreeCheckout;
    rebase(checkout: TreeCheckout): void;
    rebaseOnto(checkout: ITreeCheckout): void;
    merge(checkout: TreeCheckout): void;
    merge(checkout: TreeCheckout, disposeMerged: boolean): void;
    updateSchema(newSchema: TreeStoredSchema): void;
    dispose(): void;
    [disposeSymbol](): void;
    getRemovedRoots(): [string | number | undefined, number, JsonableTree][];
    /**
     * This must be called on the root/main checkout after loading from a summary.
     * @remarks This pattern is necessary because the EditManager skips the normal process of applying commits to branches when loading a summary.
     * Instead, it simply {@link SharedTreeBranch#setHead | mutates} the branches directly which does not propagate the typical events throughout the rest of the system.
     */
    load(): void;
    private purgeRevertibles;
    private disposeRevertible;
    private revertRevertible;
    private assertNoUntrackedRoots;
    /**
     * `true` iff the given branch change event is due to a remote change
     */
    private isRemoteChangeEvent;
    /**
     * Registers a function to be called when the given commit is validated.
     * @remarks A commit is validated by the checkout after it has been applied to the checkout's state (e.g. it has an effect on the forest).
     * If the commit applies successfully (i.e. it does not raise any unexpected errors), the commit is considered valid and the registered function is called.
     * If the commit does not apply successfully (because it causes an unexpected error), the function is not called (and the checkout will left in an error state).
     *
     * If the commit has already been validated when this function is called, the function is called immediately and this function returns `true`.
     * Otherwise, the function is registered to be called later and this function returns `false`.
     */
    onCommitValid(commit: GraphCommit<SharedTreeChange>, fn: (commit: GraphCommit<SharedTreeChange>) => void): boolean;
    /** Mark the given commit as "validated" according to the contract of {@link onCommitValid}(). */
    private validateCommit;
}
//# sourceMappingURL=treeCheckout.d.ts.map