/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
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 Revertible, type RevisionTag, type RevisionTagCodec, type TreeStoredSchema, TreeStoredSchemaRepository, type TreeStoredSchemaSubscription } from "../core/index.js";
import { type HasListeners, type IEmitter, type Listenable } from "../events/index.js";
import { type FieldBatchCodec, type TreeCompressionStrategy } from "../feature-libraries/index.js";
import { SharedTreeBranch } from "../shared-tree-core/index.js";
import { type IDisposable, TransactionResult, disposeSymbol } from "../util/index.js";
import type { SharedTreeChange } from "./sharedTreeChangeTypes.js";
import type { ISharedTreeEditor, SharedTreeEditBuilder } from "./sharedTreeEditBuilder.js";
/**
 * Events for {@link ITreeCheckout}.
 * @internal
 */
export interface CheckoutEvents {
    /**
     * A batch of changes has finished processing and the view is in a consistent state.
     * It is once again safe to access the FlexTree, Forest and AnchorSet.
     *
     * @remarks
     * This is mainly useful for knowing when to do followup work scheduled during events from Anchors.
     */
    afterBatch(): void;
    /**
     * Fired when a revertible change has been made to this view.
     *
     * Applications which subscribe to this event are expected to revert or discard revertibles they acquire (failure to do so will leak memory).
     * The provided revertible is inherently bound to the view that raised the event, calling `revert` won't apply to forked views.
     *
     * @param revertible - The revertible that can be used to revert the change.
     */
    /**
     * {@inheritdoc TreeViewEvents.commitApplied}
     */
    commitApplied(data: CommitMetadata, getRevertible?: RevertibleFactory): void;
}
/**
 * Factory for creating a {@link Revertible}.
 * Will error if invoked outside the scope of the `commitApplied` event that provides it, or if invoked multiple times.
 *
 * @param onRevertibleDisposed - A callback that will be invoked when the `Revertible` generated by this factory is disposed.
 * This happens when the `Revertible` is disposed manually, or when the `TreeView` that the `Revertible` belongs to is disposed,
 * whichever happens first.
 * This is typically used to clean up any resources associated with the `Revertible` in the host application.
 *
 * @sealed @public
 */
export type RevertibleFactory = (onRevertibleDisposed?: (revertible: Revertible) => void) => Revertible;
/**
 * 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.
 * @internal
 */
export interface ITreeCheckout extends AnchorLocator {
    /**
     * 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: ITransaction;
    /**
     * Spawn a new view which is based off of the current state of this view.
     * Any mutations of the new view will not apply to this view until the new view is merged back into this view via `merge()`.
     */
    fork(): ITreeCheckoutFork;
    /**
     * Apply all the new changes on the given view to this view.
     * @param view - a view which was created by a call to `fork()`.
     * It is automatically disposed after the merge completes.
     * @remarks All ongoing transactions (if any) in `view` will be committed before the merge.
     */
    merge(view: ITreeCheckoutFork): void;
    /**
     * Apply all the new changes on the given view to this view.
     * @param view - a view which was created by a call to `fork()`.
     * @param disposeView - whether or not to dispose `view` after the merge completes.
     * @remarks All ongoing transactions (if any) in `view` will be committed before the merge.
     */
    merge(view: ITreeCheckoutFork, disposeView: boolean): void;
    /**
     * Rebase the given view onto this view.
     * @param view - a view which was created by a call to `fork()`. It is modified by this operation.
     */
    rebase(view: 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;
    events?: Listenable<CheckoutEvents> & IEmitter<CheckoutEvents> & HasListeners<CheckoutEvents>;
    removedRoots?: DetachedFieldIndex;
    chunkCompressionStrategy?: TreeCompressionStrategy;
    logger?: ITelemetryLoggerExt;
}): TreeCheckout;
/**
 * A collection of functions for managing transactions.
 * Transactions allow edits to be batched into atomic units.
 * Edits made during a transaction will update the local state of the tree immediately, but will be squashed into a single edit when the transaction is committed.
 * If the transaction is aborted, the local state will be reset to what it was before the transaction began.
 * Transactions may nest, meaning that a transaction may be started while a transaction is already ongoing.
 *
 * To avoid updating observers of the view state with intermediate results during a transaction,
 * use {@link ITreeCheckout#fork} and {@link ISharedTreeFork#merge}.
 * @internal
 */
export interface ITransaction {
    /**
     * Start a new transaction.
     * If a transaction is already in progress when this new transaction starts, then this transaction will be "nested" inside of it,
     * i.e. the outer transaction will still be in progress after this new transaction is committed or aborted.
     *
     * @remarks - Asynchronous transactions are not supported on the root checkout,
     * since it is always kept up-to-date with the latest remote edits and the results of this rebasing (which might invalidate
     * the transaction) is not visible to the application author.
     * Instead,
     *
     * 1. fork the root checkout
     * 2. run the transaction on the fork
     * 3. merge the fork back into the root checkout
     *
     * @privateRemarks - There is currently no enforcement that asynchronous transactions don't happen on the root checkout.
     * AB#6488 tracks adding some enforcement to make it more clear to application authors that this is not supported.
     */
    start(): void;
    /**
     * Close this transaction by squashing its edits and committing them as a single edit.
     * If this is the root checkout and there are no ongoing transactions remaining, the squashed edit will be submitted to Fluid.
     */
    commit(): TransactionResult.Commit;
    /**
     * Close this transaction and revert the state of the tree to what it was before this transaction began.
     */
    abort(): TransactionResult.Abort;
    /**
     * True if there is at least one transaction currently in progress on this view, otherwise false.
     */
    inProgress(): boolean;
}
/**
 * Branch (like in a version control system) of SharedTree.
 *
 * {@link ITreeCheckout} that has forked off of the main trunk/branch.
 * @internal
 */
export interface ITreeCheckoutFork extends ITreeCheckout, IDisposable {
    /**
     * Rebase the changes that have been applied to this view over all the new changes in the given view.
     * @param view - Either the root view or a view that was created by a call to `fork()`. It is not modified by this operation.
     */
    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 {
    readonly transaction: ITransaction;
    private readonly branch;
    private readonly changeFamily;
    readonly storedSchema: TreeStoredSchemaRepository;
    readonly forest: IEditableForest;
    readonly events: Listenable<CheckoutEvents> & IEmitter<CheckoutEvents> & HasListeners<CheckoutEvents>;
    private readonly mintRevisionTag;
    private readonly revisionTagCodec;
    private readonly idCompressor;
    private readonly removedRoots;
    /** Optional logger for telemetry. */
    private readonly logger?;
    private isDisposed;
    /**
     * 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";
    constructor(transaction: ITransaction, branch: SharedTreeBranch<SharedTreeEditBuilder, SharedTreeChange>, changeFamily: ChangeFamily<SharedTreeEditBuilder, SharedTreeChange>, storedSchema: TreeStoredSchemaRepository, forest: IEditableForest, events: Listenable<CheckoutEvents> & IEmitter<CheckoutEvents> & HasListeners<CheckoutEvents>, mintRevisionTag: () => RevisionTag, revisionTagCodec: RevisionTagCodec, idCompressor: IIdCompressor, removedRoots?: DetachedFieldIndex, 
    /** Optional logger for telemetry. */
    logger?: ITelemetryLoggerExt | undefined);
    private withCombinedVisitor;
    private checkNotDisposed;
    get rootEvents(): Listenable<AnchorSetRootEvents>;
    get editor(): ISharedTreeEditor;
    locate(anchor: Anchor): AnchorNode | undefined;
    fork(): TreeCheckout;
    rebase(view: TreeCheckout): void;
    rebaseOnto(view: ITreeCheckout): void;
    merge(view: TreeCheckout): void;
    merge(view: TreeCheckout, disposeView: boolean): void;
    updateSchema(newSchema: TreeStoredSchema): void;
    [disposeSymbol](): void;
    getRemovedRoots(): [string | number | undefined, number, JsonableTree][];
    private purgeRevertibles;
    private disposeRevertible;
    private revertRevertible;
}
/**
 * Run a synchronous transaction on the given shared tree view.
 * This is a convenience helper around the {@link SharedTreeFork#transaction} APIs.
 * @param view - the view on which to run the transaction
 * @param transaction - the transaction function. This will be executed immediately. It is passed `view` as an argument for convenience.
 * If this function returns an `Abort` result then the transaction will be aborted. Otherwise, it will be committed.
 * @returns whether or not the transaction was committed or aborted
 * @internal
 */
export declare function runSynchronous(view: ITreeCheckout, transaction: (view: ITreeCheckout) => TransactionResult | void): TransactionResult;
//# sourceMappingURL=treeCheckout.d.ts.map