/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { ChangesetLocalId, RevisionTag, TaggedChange } from "../../core";
import { RangeMap } from "../../util";
import { CrossFieldManager, CrossFieldQuerySet } from "../modular-schema";
import { Attach, Detach, LineageEvent, Mark, NewAttach, Reattach, ReturnTo, NoopMark, Changeset, MoveId, Delete, CellId } from "./format";
import { MoveEffectTable } from "./moveEffectTable";
import { GenerativeMark, TransientMark, EmptyInputCellMark } from "./helperTypes";
export declare function isEmpty<T>(change: Changeset<T>): boolean;
export declare function isNewAttach<TNodeChange>(mark: Mark<TNodeChange>): mark is NewAttach<TNodeChange>;
export declare function isGenerativeMark<TNodeChange>(mark: Mark<TNodeChange>): mark is GenerativeMark<TNodeChange>;
export declare function isAttach<TNodeChange>(mark: Mark<TNodeChange>): mark is Attach<TNodeChange>;
export declare function isReattach<TNodeChange>(mark: Mark<TNodeChange>): mark is Reattach<TNodeChange>;
export declare function isActiveReattach<TNodeChange>(mark: Mark<TNodeChange>): mark is Reattach<TNodeChange> & {
    conflictsWith?: undefined;
};
export declare function isConflictedReattach<TNodeChange>(mark: Mark<TNodeChange>): boolean;
export declare function isReattachConflicted(mark: Reattach<unknown>): boolean;
export declare function isReturnMuted(mark: ReturnTo): boolean;
export declare function areEqualCellIds(a: CellId | undefined, b: CellId | undefined): boolean;
export declare function getInputCellId(mark: Mark<unknown>, revision: RevisionTag | undefined): CellId | undefined;
export declare function getOutputCellId(mark: Mark<unknown>, revision: RevisionTag | undefined): CellId | undefined;
export declare function getDetachCellId(mark: Detach<unknown>, revision: RevisionTag | undefined): CellId;
export declare function cloneMark<TMark extends Mark<TNodeChange>, TNodeChange>(mark: TMark): TMark;
export declare function cloneCellId(id: CellId): CellId;
/**
 * @param mark - The mark to get the length of.
 * @param ignorePairing - When true, the length of a paired mark (e.g. MoveIn/MoveOut) whose matching mark is not active
 * will be treated the same as if the matching mark were active.
 * @returns The number of nodes within the output context of the mark.
 */
export declare function getOutputLength(mark: Mark<unknown>, ignorePairing?: boolean): number;
/**
 * @param mark - The mark to get the length of.
 * @returns The number of nodes within the input context of the mark.
 */
export declare function getInputLength(mark: Mark<unknown>): number;
export declare function markEmptiesCells(mark: Mark<unknown>): boolean;
export declare function markFillsCells(mark: Mark<unknown>): boolean;
export declare function markHasCellEffect(mark: Mark<unknown>): boolean;
export declare function markIsTransient<T>(mark: Mark<T>): mark is TransientMark<T>;
/**
 * @returns The nested changes from `mark` if they apply to the content the mark refers to.
 */
export declare function getEffectiveNodeChanges<TNodeChange>(mark: Mark<TNodeChange>): TNodeChange | undefined;
export declare function areInputCellsEmpty<T>(mark: Mark<T>): mark is EmptyInputCellMark<T>;
export declare function areOutputCellsEmpty(mark: Mark<unknown>): boolean;
export declare function isNoopMark<T>(mark: Mark<T>): mark is NoopMark<T>;
/**
 * @returns The number of cells in the range which come before the position described by `lineage`.
 */
export declare function getOffsetInCellRange(lineage: LineageEvent[] | undefined, revision: RevisionTag | undefined, id: ChangesetLocalId, count: number): number | undefined;
export declare function areOverlappingIdRanges(id1: ChangesetLocalId, count1: number, id2: ChangesetLocalId, count2: number): boolean;
export declare function isDetachMark<TNodeChange>(mark: Mark<TNodeChange> | undefined): mark is Detach<TNodeChange>;
export declare function isDeleteMark<TNodeChange>(mark: Mark<TNodeChange> | undefined): mark is Delete<TNodeChange>;
/**
 * Attempts to extend `lhs` to include the effects of `rhs`.
 * @param lhs - The mark to extend.
 * @param rhs - The effect so extend `rhs` with.
 * @returns `true` iff the function was able to mutate `lhs` to include the effects of `rhs`.
 * When `false` is returned, `lhs` is left untouched.
 */
export declare function tryExtendMark<T>(lhs: Mark<T>, rhs: Readonly<Mark<T>>): boolean;
/**
 * Keeps track of the different ways detached nodes may be referred to.
 * Allows updating changesets so they refer to a detached node by the details
 * of the last detach that affected them.
 *
 * WARNING: this code consumes O(N) space and time for marks that affect N nodes.
 * This is code is currently meant for usage in tests.
 * It should be tested and made more efficient before production use.
 */
export declare class DetachedNodeTracker {
    private nodes;
    private readonly equivalences;
    constructor();
    /**
     * Updates the internals of this instance to account for `change` having been applied.
     * @param change - The change that is being applied. Not mutated.
     * Must be applicable (i.e., `isApplicable(change)` must be true).
     */
    apply(change: TaggedChange<Changeset<unknown>>): void;
    /**
     * Checks whether the given `change` is applicable based on previous changes.
     * @param change - The change to verify the applicability of. Not mutated.
     * @returns false iff `change`'s description of detached nodes is inconsistent with that of changes applied
     * earlier. Returns true otherwise.
     */
    isApplicable(change: Changeset<unknown>): boolean;
    /**
     * Creates an updated representation of the given `change` so that it refers to detached nodes using the revision
     * that last detached them.
     * @param change - The change to update. Not mutated.
     * Must be applicable (i.e., `isApplicable(change)` must be true).
     * @param genId - An ID allocator that produces ID unique within this changeset.
     * @returns A change equivalent to `change` that refers to detached nodes using the revision that last detached
     * them. May reuse parts of the input `change` structure.
     */
    update<T>(change: TaggedChange<Changeset<T>>): TaggedChange<Changeset<T>>;
    private updateMark;
    private getUpdatedDetach;
}
/**
 * Checks whether `branch` changeset is consistent with a `target` changeset that is may be rebased over.
 *
 * WARNING: this code consumes O(N) space and time for marks that affect N nodes.
 * This is code is currently meant for usage in tests.
 * It should be tested and made more efficient before production use.
 *
 * @param branch - The changeset that would be rebased over `target`.
 * @param target - The changeset that `branch` would be rebased over.
 * @returns false iff `branch`'s description of detached nodes is inconsistent with that of `target`.
 * Returns true otherwise.
 */
export declare function areRebasable(branch: Changeset<unknown>, target: Changeset<unknown>): boolean;
/**
 * Checks whether sequential changesets are consistent.
 *
 * WARNING: this code consumes O(N) space and time for marks that affect N nodes.
 * This is code is currently meant for usage in tests.
 * It should be tested and made more efficient before production use.
 *
 * @param changes - The changesets that would be composed together.
 * @returns false iff the changesets in `changes` are inconsistent/incompatible in their description of detached nodes.
 * Returns true otherwise.
 */
export declare function areComposable(changes: TaggedChange<Changeset<unknown>>[]): boolean;
/**
 * @alpha
 */
export interface CrossFieldTable<T = unknown> extends CrossFieldManager<T> {
    srcQueries: CrossFieldQuerySet;
    dstQueries: CrossFieldQuerySet;
    isInvalidated: boolean;
    mapSrc: Map<RevisionTag | undefined, RangeMap<T>>;
    mapDst: Map<RevisionTag | undefined, RangeMap<T>>;
    reset: () => void;
}
/**
 * @alpha
 */
export declare function newCrossFieldTable<T = unknown>(): CrossFieldTable<T>;
/**
 * @alpha
 */
export declare function newMoveEffectTable<T>(): MoveEffectTable<T>;
/**
 * Splits the `mark` into two marks such that the first returned mark has length `length`.
 * @param mark - The mark to split.
 * @param revision - The revision of the changeset the mark is part of.
 * @param length - The desired length for the first of the two returned marks.
 * @param genId - An ID allocator
 * @param moveEffects - The table in which to record splitting of move marks
 * @param recordMoveEffect - Whether when splitting a move an entry should be added to `moveEffects` indicating that the mark should be split (in case we process this mark again).
 * An entry is always added to `moveEffects` indicating that the opposite end of the move should be split.
 * @returns A pair of marks equivalent to the original `mark`
 * such that the first returned mark has input length `length`.
 */
export declare function splitMark<T, TMark extends Mark<T>>(mark: TMark, length: number): [TMark, TMark];
export declare function compareLineages(lineage1: readonly LineageEvent[] | undefined, lineage2: readonly LineageEvent[] | undefined): number;
export declare function withNodeChange<TNodeChange>(mark: Mark<TNodeChange>, changes: TNodeChange | undefined): Mark<TNodeChange>;
export declare function withRevision<TMark extends Mark<unknown>>(mark: TMark, revision: RevisionTag | undefined): TMark;
export declare function getMarkMoveId(mark: Mark<unknown>): MoveId | undefined;
//# sourceMappingURL=utils.d.ts.map