/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { ChangeFamily, ChangeFamilyEditor, GraphCommit, IRepairDataStoreProvider, RepairDataStore, UndoRedoManager, LocalCommitSource, RevisionTag } from "../core";
import { EventEmitter, ISubscribable } from "../events";
/**
 * Describes a change to a `SharedTreeBranch`. Various operations can mutate the head of the branch;
 * this change format describes each in terms of the "removed commits" (all commits which were present
 * on the branch before the operation but are no longer present after) and the "new commits" (all
 * commits which are present on the branch after the operation that were not present before). Each of
 * the following event types also provides a `change` which contains the net change to the branch
 * (or is undefined if there was no net change):
 * * Append - when one or more commits are appended to the head of the branch, for example via
 * a change applied by the branch's editor, or as a result of merging another branch into this one
 * * Remove - when one or more commits are removed from the head of the branch. This occurs
 * when a transaction is aborted and all commits pending in that transaction are removed.
 * * Replace - when an operation simultaneously removes and appends commits. For example, when this
 * branch is rebased and some commits are removed and replaced with rebased versions, or when a
 * transaction completes and all pending commits are replaced with a single squash commit.
 */
export declare type SharedTreeBranchChange<TChange> = {
    type: "append";
    change: TChange;
    newCommits: GraphCommit<TChange>[];
} | {
    type: "remove";
    change: TChange | undefined;
    removedCommits: GraphCommit<TChange>[];
} | {
    type: "replace";
    change: TChange | undefined;
    removedCommits: GraphCommit<TChange>[];
    newCommits: GraphCommit<TChange>[];
};
/**
 * Returns the operation that caused the given {@link SharedTreeBranchChange}.
 */
export declare function getChangeReplaceType(change: SharedTreeBranchChange<unknown> & {
    type: "replace";
}): "transactionCommit" | "rebase";
/**
 * The events emitted by a `SharedTreeBranch`
 */
export interface SharedTreeBranchEvents<TEditor extends ChangeFamilyEditor, TChange> {
    /**
     * Fired anytime the head of this branch changes.
     * @param change - the change to this branch's state and commits
     */
    change(change: SharedTreeBranchChange<TChange>): void;
    /**
     * Fired when a revertible change is made to this branch.
     */
    revertible(type: LocalCommitSource): void;
    /**
     * Fired when this branch forks
     * @param fork - the new branch that forked off of this branch
     */
    fork(fork: SharedTreeBranch<TEditor, TChange>): void;
    /**
     * Fired after this branch is disposed
     */
    dispose(): void;
}
/**
 * A branch of changes that can be applied to a SharedTree.
 */
export declare class SharedTreeBranch<TEditor extends ChangeFamilyEditor, TChange> extends EventEmitter<SharedTreeBranchEvents<TEditor, TChange>> {
    private head;
    readonly changeFamily: ChangeFamily<TEditor, TChange>;
    repairDataStoreProvider?: IRepairDataStoreProvider<TChange> | undefined;
    private readonly undoRedoManager?;
    readonly editor: TEditor;
    private readonly transactions;
    private disposed;
    /**
     * Construct a new branch.
     * @param head - the head of the branch
     * @param rebaser - the rebaser used for rebasing and merging commits across branches
     * @param changeFamily - determines the set of changes that this branch can commit
     * @param repairDataStoreProvider - an optional provider of {@link RepairDataStore}s to use when generating
     * repair data. This must be provided in order to use features that require repair data such as undo/redo or constraints.
     * @param undoRedoManager - an optional {@link UndoRedoManager} to manage the undo/redo operations of this
     * branch. This must be provided in order to use the `undo` and `redo` methods of this branch.
     */
    constructor(head: GraphCommit<TChange>, changeFamily: ChangeFamily<TEditor, TChange>, repairDataStoreProvider?: IRepairDataStoreProvider<TChange> | undefined, undoRedoManager?: UndoRedoManager<TChange, TEditor> | undefined);
    /**
     * Sets the head of this branch. Emits no change events.
     */
    setHead(head: GraphCommit<TChange>): void;
    /**
     * Apply a change to this branch.
     * @param change - the change to apply
     * @param revision - the revision of the new head commit of the branch that contains `change`
     * @returns the change that was applied and the new head commit of the branch
     */
    apply(change: TChange, revision: RevisionTag): [change: TChange, newCommit: GraphCommit<TChange>];
    private applyChange;
    /**
     * @returns the commit at the head of this branch.
     */
    getHead(): GraphCommit<TChange>;
    /**
     * Begin a transaction on this branch. If the transaction is committed via {@link commitTransaction},
     * all commits made since this call will be squashed into a single head commit.
     * @param repairStore - the repair store associated with this transaction
     */
    startTransaction(repairStore?: RepairDataStore<TChange>): void;
    /**
     * Commit the current transaction. There must be a transaction in progress that was begun via {@link startTransaction}.
     * If there are commits in the current transaction, they will be squashed into a new single head commit.
     * @returns the commits that were squashed and the new squash commit if a squash occurred, otherwise `undefined`.
     * @remarks If the transaction had no changes applied during its lifetime, then no squash occurs (i.e. this method is a no-op).
     * Even if the transaction contained only one change, it will still be replaced with an (equivalent) squash change.
     */
    commitTransaction(): [squashedCommits: GraphCommit<TChange>[], newCommit: GraphCommit<TChange>] | undefined;
    /**
     * Cancel the current transaction. There must be a transaction in progress that was begun via
     * {@link startTransaction}. All commits made during the transaction will be removed.
     * @returns the change to this branch resulting in the removal of the commits, and a list of the
     * commits that were removed.
     */
    abortTransaction(): [
        change: TChange | undefined,
        abortedCommits: GraphCommit<TChange>[]
    ];
    /**
     * True iff this branch is in the middle of a transaction that was begin via {@link startTransaction}
     */
    isTransacting(): boolean;
    private popTransaction;
    /**
     * Undoes the last change made by the client. If there is no change to undo then this method has no effect.
     * This method will error if no {@link UndoRedoManager} was provided when this branch was constructed.
     * It is invalid to call this method while a transaction is open (this will be supported in the future).
     * @returns the change to this branch and the new head commit, or undefined if there was nothing to undo
     */
    undo(): [change: TChange, newCommit: GraphCommit<TChange>] | undefined;
    /**
     * Redoes the last change made by the client. If there is no change to redo then this method has no effect.
     * This method will error if no {@link UndoRedoManager} was provided when this branch was constructed.
     * It is invalid to call this method while a transaction is open (this will be supported in the future).
     * @returns the change to this branch and the new head commit, or undefined if there was nothing to redo
     */
    redo(): [change: TChange, newCommit: GraphCommit<TChange>] | undefined;
    /**
     * Spawn a new branch that is based off of the current state of this branch.
     * Changes made to the new branch will not be applied to this branch until the new branch is merged back in.
     * @param repairDataStoreProvider - a {@link RepairDataStoreProvider} that reflects the state of the new branch. If one is not
     * provided, then it will be cloned from this branch.
     *
     * @remarks Forks created during a transaction will be disposed when the transaction ends.
     */
    fork(repairDataStoreProvider?: IRepairDataStoreProvider<TChange>): SharedTreeBranch<TEditor, TChange>;
    /**
     * Rebase the changes that have been applied to this branch over divergent changes in the given branch.
     * After this operation completes, this branch will be based off of `branch`.
     *
     * @remarks
     * This operation can change the relative ordering between revertible commits therefore, the revertible event
     * is not emitted during this operation.
     *
     * @param branch - the branch to rebase onto
     * @param upTo - the furthest commit on `branch` over which to rebase (inclusive). Defaults to the head commit of `branch`.
     * @returns the net change to this branch and the commits that were removed and added to this branch by the rebase,
     * or undefined if nothing changed
     */
    rebaseOnto(branch: SharedTreeBranch<TEditor, TChange>, upTo?: GraphCommit<TChange>): [
        change: TChange | undefined,
        removedCommits: GraphCommit<TChange>[],
        newCommits: GraphCommit<TChange>[]
    ] | undefined;
    /**
     * Apply all the divergent changes on the given branch to this branch.
     *
     * @remarks
     * Revertible events are emitted for new local commits merged into this branch.
     *
     * @param branch - the branch to merge into this branch
     * @returns the net change to this branch and the commits that were added to this branch by the merge,
     * or undefined if nothing changed
     */
    merge(branch: SharedTreeBranch<TEditor, TChange>): [change: TChange, newCommits: GraphCommit<TChange>[]] | undefined;
    /** Rebase `branchHead` onto `onto`, but return undefined if nothing changed */
    private rebaseBranch;
    /**
     * Dispose this branch, freezing its state.
     *
     * @remarks
     * Attempts to further mutate the branch will error.
     * Any transactions in progress will be aborted.
     * Calling dispose more than once has no effect.
     */
    dispose(): void;
    private assertNotDisposed;
}
/**
 * Registers an event listener that fires when the given forkable object forks.
 * The listener will also fire when any of those forks fork, and when those forks of forks fork, and so on.
 * @param forkable - an object that emits an event when it is forked
 * @param onFork - the fork event listener
 * @returns a function which when called will deregister all registrations (including transitive) created by this function.
 * The deregister function has undefined behavior if called more than once.
 */
export declare function onForkTransitive<T extends ISubscribable<{
    fork: (t: T) => void;
}>>(forkable: T, onFork: (fork: T) => void): () => void;
//# sourceMappingURL=branch.d.ts.map