/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { type ChangeAtomId, type ChangesetLocalId, type RevisionMetadataSource, type RevisionTag } from "../../core/index.js";
import { type RangeMap } from "../../util/index.js";
import { type CrossFieldManager, type CrossFieldQuerySet, type NodeId } from "../modular-schema/index.js";
import type { CellRename, DetachOfRemovedNodes, EmptyInputCellMark, MoveMarkEffect } from "./helperTypes.js";
import { type Attach, type AttachAndDetach, type CellId, type CellMark, type Changeset, type Detach, type Insert, type Mark, type MarkEffect, type NoopMark, type Remove } from "./types.js";
export declare function isEmpty(change: Changeset): boolean;
export declare function createEmpty(): Changeset;
export declare function getNestedChanges(change: Changeset): [NodeId, number | undefined][];
export declare function isNewAttach(mark: Mark, revision?: RevisionTag): boolean;
export declare function isNewAttachEffect(effect: MarkEffect, cellId: CellId | undefined, revision?: RevisionTag): boolean;
export declare function isInsert(mark: MarkEffect): mark is Insert;
export declare function isAttach(effect: MarkEffect): effect is Attach;
export declare function isReattach(mark: Mark): boolean;
export declare function isReattachEffect(effect: MarkEffect, cellId: CellId | undefined): boolean;
export declare function isActiveReattach(mark: Mark): mark is CellMark<Insert> & {
    conflictsWith?: undefined;
};
export declare function areEqualCellIds(a: CellId | undefined, b: CellId | undefined): boolean;
export declare function getInputCellId(mark: Mark): CellId | undefined;
export declare function getOutputCellId(mark: Mark): CellId | undefined;
export declare function cellSourcesFromMarks(marks: readonly Mark[], contextGetter: typeof getInputCellId | typeof getOutputCellId): Set<RevisionTag | undefined>;
export declare enum CellOrder {
    SameCell = 0,
    OldThenNew = 1,
    NewThenOld = 2
}
/**
 * Determines the order of two cells from two changesets.
 *
 * This function makes the following assumptions:
 * 1. The cells represent the same context.
 * 2. `oldMarkCell` is from a mark in a changeset that is older than the changeset that contains the mark that
 * `newMarkCell` is from.
 * 3. In terms of sequence index, all cells located before A are also located before B,
 * and all cells located before B are also located before A.
 * 4. If a changeset has a mark/tombstone that describes a cell named in some revision R,
 * then that changeset must contain marks/tombstones for all cells named in R as well as all cells named in later
 * revisions up to its own.
 * 5. If a changeset foo is rebased over a changeset bar, then the rebased version of foo must contain tombstones or
 * marks for all cells referenced or named in bar. It has yet to be determined whether this assumption is necessary
 * for the logic below.
 *
 * @param oldMarkCell - The cell referenced or named by a mark or tombstone from the older changeset.
 * @param newMarkCell - The cell referenced or named by a mark or tombstone from the newer changeset.
 * @param oldChangeKnowledge - The set of revisions that the older changeset has cell representations for.
 * @param newChangeKnowledge - The set of revisions that the newer changeset has cell representations for.
 * @param metadata - Revision metadata for the operation being carried out.
 * @returns a {@link CellOrder} which describes how the cells are ordered relative to one-another.
 */
export declare function compareCellPositionsUsingTombstones(oldMarkCell: ChangeAtomId, newMarkCell: ChangeAtomId, oldChangeKnowledge: ReadonlySet<RevisionTag | undefined>, newChangeKnowledge: ReadonlySet<RevisionTag | undefined>, metadata: RevisionMetadataSource): CellOrder;
/**
 * @returns the ID of the cell in the output context of the given detach `mark`.
 */
export declare function getDetachOutputCellId(mark: Detach): ChangeAtomId;
/**
 * @returns the ID of the detached node in the output context of the given detach `mark`.
 */
export declare function getDetachedNodeId(mark: Detach): ChangeAtomId;
/**
 * Preserves the semantics of the given `mark` but repackages it into a `DetachOfRemovedNodes` when possible.
 */
export declare function normalizeCellRename(mark: CellMark<AttachAndDetach>): CellMark<AttachAndDetach | DetachOfRemovedNodes>;
/**
 * Preserves the semantics of the given `mark` but repackages it into an `AttachAndDetach` mark if it is not already one.
 */
export declare function asAttachAndDetach(mark: CellMark<CellRename>): CellMark<AttachAndDetach>;
export declare function cloneMark<TMark extends Mark>(mark: TMark): TMark;
export declare function cloneMarkEffect<TEffect extends MarkEffect>(effect: TEffect): TEffect;
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, 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): number;
export declare function markEmptiesCells(mark: Mark): boolean;
export declare function markFillsCells(mark: Mark): boolean;
export declare function markHasCellEffect(mark: Mark): boolean;
export declare function isAttachAndDetachEffect(effect: MarkEffect): effect is AttachAndDetach;
export declare function isDetachOfRemovedNodes(mark: Mark): mark is CellMark<DetachOfRemovedNodes>;
export declare function isImpactfulCellRename(mark: Mark): mark is CellMark<CellRename>;
export declare function areInputCellsEmpty(mark: Mark): mark is EmptyInputCellMark;
export declare function areOutputCellsEmpty(mark: Mark): boolean;
/**
 * Creates a mark that is equivalent to the given `mark` but with effects removed if those have no impact in the input
 * context of that mark.
 *
 * @param mark - The mark to settle. Never mutated.
 * @returns either the original mark or a shallow clone of it with effects stripped out.
 */
export declare function settleMark(mark: Mark): Mark;
/**
 * @returns true, iff the given `mark` would have impact on the field when applied.
 * Ignores the impact of nested changes.
 * CellRename effects are considered impactful if they actually change the ID of the cells.
 */
export declare function isImpactful(mark: Mark): boolean;
export declare function isTombstone(mark: Mark): mark is CellMark<NoopMark> & {
    cellId: CellId;
};
export declare function isNoopMark(mark: Mark): mark is CellMark<NoopMark>;
export declare function areOverlappingIdRanges(id1: ChangesetLocalId, count1: number, id2: ChangesetLocalId, count2: number): boolean;
export declare function compareCellsFromSameRevision(cell1: CellId, count1: number, cell2: CellId, count2: number): number | undefined;
export declare function isDetach(mark: MarkEffect | undefined): mark is Detach;
export declare function isRemoveMark(mark: Mark | undefined): mark is CellMark<Remove>;
/**
 * 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 `lhs` iff the function was able to mutate `lhs` to include the effects of `rhs`.
 * When `undefined` is returned, `lhs` is left untouched.
 */
export declare function tryMergeMarks(lhs: Mark, rhs: Readonly<Mark>): Mark | undefined;
/**
 * @internal
 */
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;
}
/**
 * @internal
 */
export declare function newCrossFieldTable<T = unknown>(): CrossFieldTable<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<TMark extends Mark>(mark: TMark, length: number): [TMark, TMark];
export declare function splitMarkEffect<TEffect extends MarkEffect>(effect: TEffect, length: number): [TEffect, TEffect];
export declare function extractMarkEffect<TEffect extends MarkEffect>(mark: CellMark<TEffect>): TEffect;
export declare function omitMarkEffect(mark: CellMark<unknown>): CellMark<NoopMark>;
export declare function withNodeChange<TMark extends CellMark<TKind>, TKind extends MarkEffect>(mark: TMark, changes: NodeId | undefined): TMark;
export declare function withRevision<TMark extends Mark>(mark: TMark, revision: RevisionTag | undefined): TMark;
export declare function getEndpoint(effect: MoveMarkEffect): ChangeAtomId;
//# sourceMappingURL=utils.d.ts.map