import { OperationSequenceNode, TransformationFactory } from "../types/history";
import { UID } from "../types/misc";
import { Branch } from "./branch";
import { Operation } from "./operation";
import { OperationSequence } from "./operation_sequence";
/**
 * The tree is a data structure used to maintain the different branches of the
 * SelectiveHistory.
 *
 * Branches can be "stacked" on each other and an execution path can be derived
 * from any stack of branches. The rules to derive this path is explained below.
 *
 * An operation can be cancelled/undone by inserting a new branch below
 * this operation.
 * e.g
 *    Given the branch A    B   C
 *    To undo B, a new branching branch is inserted at operation B.
 *    ```txt
 *    A   B   C   D
 *        >   C'  D'
 *    ```
 *    A new execution path can now be derived. At each operation:
 *    - if there is a lower branch, don't execute it and go to the operation below
 *    - if not, execute it and go to the operation on the right.
 *    The execution path is   A   C'    D'
 *    Operation C and D have been adapted (transformed) in the lower branch
 *    since operation B is not executed in this branch.
 *
 */
export declare class Tree<T = unknown> {
    private readonly buildTransformation;
    private readonly branches;
    private branchingOperationIds;
    constructor(buildTransformation: TransformationFactory<T>, initialBranch: Branch<T>);
    /**
     * Return the last branch of the entire stack of branches.
     */
    getLastBranch(): Branch<T>;
    /**
     * Return the sequence of operations from this branch
     * until the very last branch.
     */
    execution(branch: Branch<T>): OperationSequence<T>;
    /**
     * Return the sequence of operations from this branch
     * to the very first branch.
     */
    revertedExecution(branch: Branch<T>): OperationSequence<T>;
    /**
     * Append an operation to the end of the tree.
     * Also insert the (transformed) operation in all previous branches.
     *
     * Adding operation `D` to the last branch
     * ```txt
     *  A1   B1   C1
     *  >    B2   C2
     * ```
     * will give
     * ```txt
     *  A1   B1   C1   D'   with D' = D transformed with A1
     *  >    B2   C2   D
     * ```
     */
    insertOperationLast(branch: Branch<T>, operation: Operation<T>): void;
    /**
     * Insert a new operation after an other operation.
     * The operation will be inserted in this branch, in next branches (transformed)
     * and in previous branches (also transformed).
     *
     * Given
     * ```txt
     *  1: A1   B1   C1
     *  2: >    B2   C2
     *  3:      >    C3
     * ```
     * Inserting D to branch 2 gives
     * ```txt
     *  1: A1   B1   C1   D1          D1 = D transformed with A1
     *  2: >    B2   C2   D     with  D  = D
     *  3:      >    C3   D2          D2 = D transformed without B2 (B2⁻¹)
     * ```
     */
    insertOperationAfter(branch: Branch<T>, operation: Operation<T>, predecessorOpId: UID): void;
    /**
     * Create a new branching branch at the given operation.
     * This cancels the operation from the execution path.
     */
    undo(branch: Branch<T>, operation: Operation<T>): void;
    /**
     * Remove the branch just after this one. This un-cancels (redo) the branching
     * operation. Lower branches will be transformed accordingly.
     *
     * Given
     * ```txt
     *  1: A1   B1   C1
     *  2: >    B2   C2
     *  3:      >    C3
     * ```
     * removing the next branch of 1 gives
     *
     * ```txt
     *  1: A1   B1   C1
     *  2:      >    C3'   with  C3' = C1 transformed without B1 (B1⁻¹)
     * ```
     */
    redo(branch: Branch<T>): void;
    /**
     * Drop the operation and all following operations in every
     * branches
     */
    drop(operationId: UID): void;
    /**
     * Find the operation in the execution path.
     */
    findOperation(branch: Branch<T>, operationId: UID): OperationSequenceNode<T>;
    /**
     * Rebuild transformed operations of this branch based on the upper branch.
     *
     * Given the following structure:
     * ```txt
     *  1: A1   B1    C1
     *  2: >    B2    C2
     *  3:      >     C3
     * ```
     * Rebasing branch "2" gives
     * ```txt
     *  1: A1   B1    C1
     *  2: >    B2'   C2'  With  B2' = B1 transformed without A1 and C2' = C1 transformed without A1
     *  3:      >     C3'        C3' = C2' transformed without B2'
     * ```
     */
    private rebaseUp;
    private removeBranchFromTree;
    private insertBranchAfter;
    /**
     * Update the branching branch of this branch, either by (1) inserting the new
     * operation in it or (2) by transforming it.
     * (1) If the operation is positioned before the branching branch, the branching
     *     branch should be transformed with this operation.
     * (2) If it's positioned after, the operation should be inserted in the
     *     branching branch.
     */
    private updateNextWith;
    private addToNextBranch;
    private getTransformedOperation;
    /**
     * Check if this branch should execute the given operation.
     * i.e. If the operation is not cancelled by a branching branch.
     */
    private shouldExecute;
    private transform;
    /**
     * Insert a new operation in previous branches. The operations which are
     * positioned after the inserted operations are transformed with the newly
     * inserted operations. This one is also transformed, with the branching
     * operation.
     */
    private insertPrevious;
    private findPreviousBranchingOperation;
    /**
     * Retrieve the next branch of the given branch
     */
    private nextBranch;
    /**
     * Retrieve the previous branch of the given branch
     */
    private previousBranch;
    /**
     * Yields the sequence of operations to execute, in reverse order.
     */
    private _revertedExecution;
    /**
     * Yields the sequence of operations to execute
     */
    private _execution;
}
