import { AttributionKey } from '@fluidframework/runtime-definitions';
import { Heap } from '@fluidframework/core-utils';
import { IChannelStorageService } from '@fluidframework/datastore-definitions';
import { IEventThisPlaceHolder } from '@fluidframework/core-interfaces';
import { IFluidDataStoreRuntime } from '@fluidframework/datastore-definitions';
import { IFluidHandle } from '@fluidframework/core-interfaces';
import { IFluidSerializer } from '@fluidframework/shared-object-base';
import { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions';
import { ISummaryTreeWithStats } from '@fluidframework/runtime-definitions';
import { ITelemetryLoggerExt } from '@fluidframework/telemetry-utils';
import { TypedEventEmitter } from '@fluid-internal/client-utils';

/* Excluded from this release type: addProperties */

/* Excluded from this release type: appendToMergeTreeDeltaRevertibles */

/**
 * Implements policy dictating which kinds of operations should be attributed and how.
 * @sealed
 * @alpha
 */
export declare interface AttributionPolicy {
    /**
     * Enables tracking attribution information for operations on this merge-tree.
     * This function is expected to subscribe to appropriate change events in order
     * to manage any attribution data it stores on segments.
     *
     * This must be done in an eventually consistent fashion.
     */
    attach: (client: Client) => void;
    /**
     * Disables tracking attribution information on segments.
     */
    detach: () => void;
    /***/
    isAttached: boolean;
    /**
     * Serializer capable of serializing any attribution data this policy stores on segments.
     */
    serializer: IAttributionCollectionSerializer;
}

/**
 * This is a special segment that is not bound or known by the merge tree itself,
 * but the segment itself pretends to be a removed segment at an endpoint of the
 * tree. It is removed so it appears as a undefined/0 length segment. This segment
 * adds the capability to hold local references that have been detached from the
 * real merge tree, and give the appearance that they exist at an endpoint of the
 * tree.
 *
 * This is useful today in 2 cases: detached references and interval stickiness.
 *
 * In general, local references only become detached when the tree becomes empty
 * and the EndOfTreeSegment allows us to gracefully handle that case by giving
 * those references a place to live.
 *
 * In the case of interval stickiness, it is desirable to be able to refer to
 * the position immediately after or before a segment, in order for the endpoint
 * of an interval to be exclusive. This means that in order to support intervals
 * that are exclusive and also include the first or last segment of the tree, it
 * must be possible in some way to refer to a position before or after the tree
 * respectively. The endpoint segments allow us to support such behavior.
 */
declare abstract class BaseEndpointSegment {
    protected readonly mergeTree: MergeTree;
    constructor(mergeTree: MergeTree);
    removedSeq: number;
    removedClientIds: number[];
    attribution: undefined;
    propertyManager: undefined;
    localSeq: undefined;
    localRemovedSeq: undefined;
    properties: undefined;
    seq: number;
    clientId: number;
    cachedLength: number;
    isLeaf(): this is ISegment;
    protected abstract endpointSegmentProps(): {
        parent: IMergeBlock;
        index: number;
        depth: number;
    };
    get parent(): IMergeBlock;
    get index(): number;
    abstract get ordinal(): string;
    localRefs?: LocalReferenceCollection;
    get segmentGroups(): never;
    get trackingCollection(): never;
    addProperties: () => never;
    clone: () => never;
    canAppend: () => never;
    append: () => never;
    splitAt: () => never;
    toJSONObject: () => never;
    ack: () => never;
}

/**
 * @alpha
 */
export declare abstract class BaseSegment extends MergeNode implements ISegment {
    clientId: number;
    seq: number;
    removedSeq?: number;
    removedClientIds?: number[];
    movedSeq?: number;
    movedSeqs?: number[];
    movedClientIds?: number[];
    wasMovedOnInsert?: boolean | undefined;
    readonly segmentGroups: SegmentGroupCollection;
    readonly trackingCollection: TrackingGroupCollection;
    /***/
    attribution?: IAttributionCollection<AttributionKey>;
    propertyManager?: PropertiesManager;
    properties?: PropertySet;
    localRefs?: LocalReferenceCollection;
    abstract readonly type: string;
    localSeq?: number;
    localRemovedSeq?: number;
    localMovedSeq?: number;
    addProperties(newProps: PropertySet, seq?: number, collaborating?: boolean, rollback?: PropertiesRollback): PropertySet;
    hasProperty(key: string): boolean;
    isLeaf(): this is ISegment;
    protected cloneInto(b: ISegment): void;
    canAppend(segment: ISegment): boolean;
    protected addSerializedProps(jseg: IJSONSegment): void;
    abstract toJSONObject(): any;
    /***/
    ack(segmentGroup: SegmentGroup, opArgs: IMergeTreeDeltaOpArgs): boolean;
    splitAt(pos: number): ISegment | undefined;
    private copyPropertiesTo;
    abstract clone(): ISegment;
    append(other: ISegment): void;
    protected abstract createSplitSegmentAt(pos: number): BaseSegment | undefined;
}

/**
 * @deprecated This functionality was not meant to be exported and will be removed in a future release
 * @alpha
 */
export declare class Client extends TypedEventEmitter<IClientEvents> {
    readonly specToSegment: (spec: IJSONSegment) => ISegment;
    readonly logger: ITelemetryLoggerExt;
    longClientId: string | undefined;
    private readonly _mergeTree;
    private readonly clientNameToIds;
    private readonly shortClientIdMap;
    constructor(specToSegment: (spec: IJSONSegment) => ISegment, logger: ITelemetryLoggerExt, options?: IMergeTreeOptions & PropertySet);
    /**
     * The merge tree maintains a queue of segment groups for each local operation.
     * These segment groups track segments modified by an operation.
     * This method peeks the tail of that queue, and returns the segments groups there.
     * It is used to get the segment group(s) for the previous operations.
     * @param count - The number segment groups to get peek from the tail of the queue. Default 1.
     */
    peekPendingSegmentGroups(): SegmentGroup | undefined;
    peekPendingSegmentGroups(count: number): SegmentGroup | SegmentGroup[] | undefined;
    /**
     * Annotates the markers with the provided properties
     * @param marker - The marker to annotate
     * @param props - The properties to annotate the marker with
     * @returns The annotate op if valid, otherwise undefined
     */
    annotateMarker(marker: Marker, props: PropertySet): IMergeTreeAnnotateMsg | undefined;
    /**
     * Annotates the range with the provided properties
     * @param start - The inclusive start position of the range to annotate
     * @param end - The exclusive end position of the range to annotate
     * @param props - The properties to annotate the range with
     * @returns The annotate op if valid, otherwise undefined
     */
    annotateRangeLocal(start: number, end: number, props: PropertySet): IMergeTreeAnnotateMsg | undefined;
    /**
     * Removes the range
     *
     * @param start - The inclusive start of the range to remove
     * @param end - The exclusive end of the range to remove
     */
    removeRangeLocal(start: number, end: number): IMergeTreeRemoveMsg;
    /**
     * Obliterates the range. This is similar to removing the range, but also
     * includes any concurrently inserted content.
     *
     * @param start - The inclusive start of the range to obliterate
     * @param end - The exclusive end of the range to obliterate
     */
    obliterateRangeLocal(start: number, end: number): IMergeTreeObliterateMsg;
    /**
     * @param pos - The position to insert the segment at
     * @param segment - The segment to insert
     */
    insertSegmentLocal(pos: number, segment: ISegment): IMergeTreeInsertMsg | undefined;
    /**
     * @param refPos - The reference position to insert the segment at
     * @param segment - The segment to insert
     */
    insertAtReferencePositionLocal(refPos: ReferencePosition, segment: ISegment): IMergeTreeInsertMsg | undefined;
    walkSegments<TClientData>(handler: ISegmentAction<TClientData>, start: number | undefined, end: number | undefined, accum: TClientData, splitRange?: boolean): void;
    walkSegments<undefined>(handler: ISegmentAction<undefined>, start?: number, end?: number, accum?: undefined, splitRange?: boolean): void;
    protected walkAllSegments<TClientData>(action: (segment: ISegment, accum?: TClientData) => boolean, accum?: TClientData): boolean;
    /**
     * Serializes the data required for garbage collection. The IFluidHandles stored in all segments that haven't
     * been removed represent routes to other objects. We serialize the data in these segments using the passed in
     * serializer which keeps track of all serialized handles.
     */
    serializeGCData(handle: IFluidHandle, handleCollectingSerializer: IFluidSerializer): void;
    getCollabWindow(): CollaborationWindow;
    /**
     * Returns the current position of a segment, and -1 if the segment
     * does not exist in this merge tree
     * @param segment - The segment to get the position of
     */
    getPosition(segment: ISegment | undefined, localSeq?: number): number;
    /**
     * Creates a `LocalReferencePosition` on this client. If the refType does not include ReferenceType.Transient,
     * the returned reference will be added to the localRefs on the provided segment.
     * @param segment - Segment to add the local reference on
     * @param offset - Offset on the segment at which to place the local reference
     * @param refType - ReferenceType for the created local reference
     * @param properties - PropertySet to place on the created local reference
     * @param canSlideToEndpoint - Whether or not the created local reference can
     * slide onto one of the special endpoint segments denoting the position
     * before the start of or after the end of the tree
     */
    createLocalReferencePosition(segment: ISegment | "start" | "end", offset: number | undefined, refType: ReferenceType, properties: PropertySet | undefined, slidingPreference?: SlidingPreference, canSlideToEndpoint?: boolean): LocalReferencePosition;
    /**
     * Removes a `LocalReferencePosition` from this client.
     */
    removeLocalReferencePosition(lref: LocalReferencePosition): LocalReferencePosition | undefined;
    /**
     * Resolves a `ReferencePosition` into a character position using this client's perspective.
     */
    localReferencePositionToPosition(lref: ReferencePosition): number;
    /**
     * Given a position specified relative to a marker id, lookup the marker
     * and convert the position to a character position.
     * @param relativePos - Id of marker (may be indirect) and whether position is before or after marker.
     */
    posFromRelativePos(relativePos: IRelativePosition): number;
    getMarkerFromId(id: string): ISegment | undefined;
    /**
     * Revert an op
     */
    rollback?(op: any, localOpMetadata: unknown): void;
    private applyObliterateRangeOp;
    /**
     * Performs the remove based on the provided op
     * @param opArgs - The ops args for the op
     */
    private applyRemoveRangeOp;
    /**
     * Performs the annotate based on the provided op
     * @param opArgs - The ops args for the op
     */
    private applyAnnotateRangeOp;
    /**
     * Performs the insert based on the provided op
     * @param opArgs - The ops args for the op
     * @returns True if the insert was applied. False if it could not be.
     */
    private applyInsertOp;
    /**
     * Returns a valid range for the op, or undefined
     * @param op - The op to generate the range for
     * @param clientArgs - The client args for the op
     */
    private getValidOpRange;
    /**
     * Gets the client args from the op if remote, otherwise uses the local clients info
     * @param sequencedMessage - The sequencedMessage to get the client sequence args for
     */
    private getClientSequenceArgsForMessage;
    /**
     * Gets the client args from the op if remote, otherwise uses the local clients info
     * @param opArgs - The op arg to get the client sequence args for
     */
    private getClientSequenceArgs;
    private ackPendingSegment;
    getOrAddShortClientId(longClientId: string): number;
    protected getShortClientId(longClientId: string): number;
    getLongClientId(shortClientId: number): string;
    addLongClientId(longClientId: string): void;
    private getOrAddShortClientIdFromMessage;
    /**
     * During reconnect, we must find the positions to pending segments
     * relative to other pending segments. This methods computes that
     * position relative to a localSeq. Pending segments above the localSeq
     * will be ignored.
     *
     * @param segment - The segment to find the position for
     * @param localSeq - The localSeq to find the position of the segment at
     */
    findReconnectionPosition(segment: ISegment, localSeq: number): number;
    private resetPendingDeltaToOps;
    private applyRemoteOp;
    applyStashedOp(op: IMergeTreeDeltaOp): SegmentGroup;
    applyStashedOp(op: IMergeTreeGroupMsg): SegmentGroup[];
    applyStashedOp(op: IMergeTreeOp): SegmentGroup | SegmentGroup[];
    applyMsg(msg: ISequencedDocumentMessage, local?: boolean): void;
    private updateSeqNumbers;
    /**
     * Resolves a remote client's position against the local sequence
     * and returns the remote client's position relative to the local
     * sequence
     * @param remoteClientPosition - The remote client's position to resolve
     * @param remoteClientRefSeq - The reference sequence number of the remote client
     * @param remoteClientId - The client id of the remote client
     */
    resolveRemoteClientPosition(remoteClientPosition: number, remoteClientRefSeq: number, remoteClientId: string): number | undefined;
    private lastNormalizationRefSeq;
    private pendingRebase;
    /**
     * Given a pending operation and segment group, regenerate the op, so it
     * can be resubmitted
     * @param resetOp - The op to reset
     * @param segmentGroup - The segment group associated with the op
     */
    regeneratePendingOp(resetOp: IMergeTreeOp, segmentGroup: SegmentGroup | SegmentGroup[]): IMergeTreeOp;
    createTextHelper(): IMergeTreeTextHelper;
    summarize(runtime: IFluidDataStoreRuntime, handle: IFluidHandle, serializer: IFluidSerializer, catchUpMsgs: ISequencedDocumentMessage[]): ISummaryTreeWithStats;
    load(runtime: IFluidDataStoreRuntime, storage: IChannelStorageService, serializer: IFluidSerializer): Promise<{
        catchupOpsP: Promise<ISequencedDocumentMessage[]>;
    }>;
    private getLocalSequenceNumber;
    localTransaction(groupOp: IMergeTreeGroupMsg): void;
    updateMinSeq(minSeq: number): void;
    getContainingSegment<T extends ISegment>(pos: number, sequenceArgs?: Pick<ISequencedDocumentMessage, "referenceSequenceNumber" | "clientId">, localSeq?: number): {
        segment: T | undefined;
        offset: number | undefined;
    };
    getPropertiesAtPosition(pos: number): PropertySet | undefined;
    getRangeExtentsOfPosition(pos: number): {
        posStart: number | undefined;
        posAfterEnd: number | undefined;
    };
    getCurrentSeq(): number;
    getClientId(): number;
    getLength(): number;
    startOrUpdateCollaboration(longClientId: string | undefined, minSeq?: number, currentSeq?: number): void;
    /**
     * @deprecated Use searchForMarker instead.
     */
    findTile(startPos: number, tileLabel: string, preceding?: boolean): {
        tile: ReferencePosition;
        pos: number;
    } | undefined;
    /**
     * Searches a string for the nearest marker in either direction to a given start position.
     * The search will include the start position, so markers at the start position are valid
     * results of the search. Makes use of block-accelerated search functions for log(n) complexity.
     *
     * @param startPos - Position at which to start the search
     * @param markerLabel - Label of the marker to search for
     * @param forwards - Whether the desired marker comes before (false) or after (true) `startPos`
     */
    searchForMarker(startPos: number, markerLabel: string, forwards?: boolean): Marker | undefined;
}

/**
 * @deprecated This functionality was not meant to be exported and will be removed in a future release
 * @alpha
 */
export declare class CollaborationWindow {
    clientId: number;
    collaborating: boolean;
    /**
     * Lowest-numbered segment in window; no client can reference a state before this one
     */
    minSeq: number;
    /**
     * Highest-numbered segment in window and current reference sequence number for this client.
     */
    currentSeq: number;
    /**
     * Highest-numbered localSeq used for a pending segment.
     * Semantically, `localSeq`s provide an ordering on in-flight merge-tree operations:
     * for operations stamped with localSeqs `a` and `b`, `a < b` if and only if `a` was submitted before `b`.
     *
     * @remarks - This field is analogous to the `clientSequenceNumber` field on ops, but it's accessible to merge-tree
     * at op submission time rather than only at ack time. This enables more natural state tracking for in-flight ops.
     *
     * It's useful to stamp ops with such an incrementing counter because it enables reasoning about which segments existed from
     * the perspective of the local client at a given point in 'un-acked' time, which is necessary to support the reconnect flow.
     *
     * For example, imagine a client with initial state "123456" submits some ops to create the text "123456ABC".
     * If they insert the "C" first, then "B", then "A", their local segment state might look like this:
     * ```js
     * [
     *     { seq: 0, text: "1234" },
     *     { seq: 5, text: "56" },
     *     { localSeq: 3, seq: UnassignedSequenceNumber, text: "A" },
     *     { localSeq: 2, seq: UnassignedSequenceNumber, text: "B" },
     *     { localSeq: 1, seq: UnassignedSequenceNumber, text: "C" },
     * ]
     * ```
     * (note that {@link ISegment.localSeq} tracks the localSeq at which a segment was inserted)
     *
     * Suppose the client then disconnects and reconnects before any of its insertions are acked. The reconnect flow will necessitate
     * that the client regenerates and resubmits ops based on its current segment state as well as the original op that was sent.
     *
     * It will generate the ops
     * 1. \{ pos: 6, text: "C" \}
     * 2. \{ pos: 6, text: "B" \}
     * 3. \{ pos: 6, text: "A" \}
     *
     * since when submitting the first op, remote clients don't know that this client is about to submit the "A" and "B".
     *
     * On the other hand, imagine if the client had originally submitted the ops in the order "A", "B", "C"
     * such that the segments' local state was instead:
     *
     * ```js
     * [
     *     { seq: 0, text: "1234" },
     *     { seq: 5, text: "56" },
     *     { localSeq: 1, seq: UnassignedSequenceNumber, text: "A" },
     *     { localSeq: 2, seq: UnassignedSequenceNumber, text: "B" },
     *     { localSeq: 3, seq: UnassignedSequenceNumber, text: "C" },
     * ]
     * ```
     *
     * The resubmitted ops should instead be:
     * 1. \{ pos: 6, text: "A" \}
     * 2. \{ pos: 7, text: "B" \}
     * 3. \{ pos: 8, text: "C" \}
     *
     * since remote clients will have seen the "A" when processing the "B" as well as both the "A" and "B" when processing the "C".
     * As can be seen, the list of resubmitted ops is different in the two cases despite the merge-tree's segment state only differing
     * in `localSeq`.
     *
     * This example is a bit simplified from the general scenario: since no remote clients modified the merge-tree while the client
     * was disconnected, the resubmitted ops end up matching the original ops exactly.
     * However, this is not generally true: the production reconnect code takes into account visibility of segments based on both acked
     * and local information as appropriate.
     * Nonetheless, this simple scenario is enough to understand why it's useful to be able to determine if a segment should be visible
     * from a given (seq, localSeq) perspective.
     */
    localSeq: number;
    loadFrom(a: CollaborationWindow): void;
}

/* Excluded from this release type: compareReferencePositions */

/* Excluded from this release type: ConflictAction */

/* Excluded from this release type: createAnnotateRangeOp */

/* Excluded from this release type: createDetachedLocalReferencePosition */

/* Excluded from this release type: createGroupOp */

/* Excluded from this release type: createInsertOnlyAttributionPolicy */

/* Excluded from this release type: createInsertOp */

/* Excluded from this release type: createInsertSegmentOp */

/* Excluded from this release type: createMap */

/* Excluded from this release type: createObliterateRangeOp */

/* Excluded from this release type: createRemoveRangeOp */

/* Excluded from this release type: debugMarkerToString */

/* Excluded from this release type: DetachedReferencePosition */

/* Excluded from this release type: Dictionary */

/* Excluded from this release type: discardMergeTreeDeltaRevertible */

declare class DoublyLinkedList<T> implements Iterable<ListNode<T>>, Partial<ListNodeRange<T>>, Pick<ListNode<T>[], "pop" | "shift" | "length" | "includes"> {
    find(predicate: (value: ListNode<T>, obj: DoublyLinkedList<T>) => unknown): ListNode<T> | undefined;
    map<U>(callbackfn: (value: ListNode<T>) => U): Iterable<U>;
    insertAfter(preceding: ListNode<T>, ...items: T[]): ListNodeRange<T>;
    pop(): ListNode<T> | undefined;
    push(...items: T[]): ListNodeRange<T>;
    /**
     * Remove and return the first element
     */
    shift(): ListNode<T> | undefined;
    /**
     * Insert `items` at start of list
     */
    unshift(...items: T[]): ListNodeRange<T>;
    /**
     * Remove nodes starting at `start` until either the `end` node is reached
     * or until `count` nodes have been removed. Returns the removed nodes as
     * a separate linked list
     */
    splice(start: ListNode<T>, countOrEnd?: ListNode<T> | number): DoublyLinkedList<T>;
    includes(node: ListNode<T> | undefined): node is ListNode<T>;
    private _includes;
    private _remove;
    remove(node: ListNode<T> | undefined): ListNode<T> | undefined;
    [Symbol.iterator](): IterableIterator<ListNode<T>>;
    private _len;
    private readonly headNode;
    get length(): number;
    get empty(): boolean;
    get first(): ListNode<T> | undefined;
    get last(): ListNode<T> | undefined;
}

/**
 * The position immediately after the end of the tree
 */
declare class EndOfTreeSegment extends BaseEndpointSegment implements ISegment, IRemovalInfo {
    type: string;
    readonly endpointType = "end";
    /**
     * this segment pretends to be a sibling of the last real segment.
     * so compute the necessary properties to pretend to be that segment.
     */
    protected endpointSegmentProps(): {
        parent: IMergeBlock;
        index: number;
        depth: number;
    };
    get ordinal(): string;
}

/* Excluded from this release type: getSlideToSegoff */

/* Excluded from this release type: Heap */

/**
 * @alpha
 */
export declare interface IAttributionCollection<T> {
    /**
     * Retrieves the attribution key associated with the provided offset.
     * @param channel - When specified, gets an attribution key associated with a particular channel.
     */
    getAtOffset(offset: number, channel?: string): AttributionKey | undefined;
    /**
     * Total length of all attribution keys in this collection.
     */
    readonly length: number;
    readonly channelNames: Iterable<string>;
    /**
     * Retrieve all key/offset pairs stored on this segment. Entries should be ordered by offset, such that
     * the `i`th result's attribution key applies to offsets in the open range between the `i`th offset and the
     * `i+1`th offset.
     * The last entry's key applies to the open interval from the last entry's offset to this collection's length.
     */
    getAll(): IAttributionCollectionSpec<T>;
    /***/
    splitAt(pos: number): IAttributionCollection<T>;
    /***/
    append(other: IAttributionCollection<T>): void;
    /***/
    clone(): IAttributionCollection<T>;
    /**
     * Updates this collection with new attribution data.
     * @param name - Name of the channel that requires an update. Undefined signifies the root channel.
     * Updates apply only to the individual channel (i.e. if an attribution policy needs to update the root
     * channel and 4 other channels, it should call `.update` 5 times).
     * @param channel - Updated collection for that channel.
     */
    update(name: string | undefined, channel: IAttributionCollection<T>): void;
}

/**
 * @alpha
 * @sealed
 */
export declare interface IAttributionCollectionSerializer {
    /***/
    serializeAttributionCollections(segments: Iterable<{
        attribution?: IAttributionCollection<AttributionKey>;
        cachedLength: number;
    }>): SerializedAttributionCollection;
    /**
     * Populates attribution information on segments using the provided summary.
     */
    populateAttributionCollections(segments: Iterable<ISegment>, summary: SerializedAttributionCollection): void;
}

/**
 * @alpha
 */
export declare interface IAttributionCollectionSpec<T> {
    root: Iterable<{
        offset: number;
        key: T | null;
    }>;
    channels?: {
        [name: string]: Iterable<{
            offset: number;
            key: T | null;
        }>;
    };
    length: number;
}

/**
 * Emitted before this client's merge-tree normalizes its segments on reconnect, potentially
 * ordering them. Useful for DDS-like consumers built atop the merge-tree to compute any information
 * they need for rebasing their ops on reconnection.
 * @alpha
 */
export declare interface IClientEvents {
    (event: "normalize", listener: (target: IEventThisPlaceHolder) => void): void;
    (event: "delta", listener: (opArgs: IMergeTreeDeltaOpArgs, deltaArgs: IMergeTreeDeltaCallbackArgs, target: IEventThisPlaceHolder) => void): void;
    (event: "maintenance", listener: (args: IMergeTreeMaintenanceCallbackArgs, deltaArgs: IMergeTreeDeltaOpArgs | undefined, target: IEventThisPlaceHolder) => void): void;
}

/* Excluded from this release type: IHierBlock */

/**
 * @alpha
 */
export declare interface IJSONMarkerSegment extends IJSONSegment {
    marker: IMarkerDef;
}

/**
 * @alpha
 */
export declare interface IJSONSegment {
    props?: Record<string, any>;
}

/**
 * @alpha
 */
export declare interface IJSONTextSegment extends IJSONSegment {
    text: string;
}

/**
 * @alpha
 */
export declare interface IMarkerDef {
    refType?: ReferenceType;
}

/* Excluded from this release type: IMergeBlock */

declare type IMergeLeaf = ISegment & {
    parent?: IMergeBlock;
};

declare type IMergeNode = IMergeBlock | IMergeLeaf;

/**
 * Common properties for a node in a merge tree.
 * @alpha
 */
export declare interface IMergeNodeCommon {
    /**
     * The index of this node in its parent's list of children.
     */
    index: number;
    /**
     * A string that can be used for comparing the location of this node to other `MergeNode`s in the same tree.
     * `a.ordinal < b.ordinal` if and only if `a` comes before `b` in a pre-order traversal of the tree.
     */
    ordinal: string;
    isLeaf(): this is ISegment;
}

/**
 * @alpha
 */
export declare interface IMergeTreeAnnotateMsg extends IMergeTreeDelta {
    type: typeof MergeTreeDeltaType.ANNOTATE;
    pos1?: number;
    relativePos1?: IRelativePosition;
    pos2?: number;
    relativePos2?: IRelativePosition;
    props: Record<string, any>;
}

/**
 * @alpha
 */
export declare interface IMergeTreeAttributionOptions {
    /**
     * If enabled, segments will store attribution keys which can be used with the runtime to determine
     * attribution information (i.e. who created the content and when it was created).
     *
     * This flag only applied to new documents: if a snapshot is loaded, whether or not attribution keys
     * are tracked is determined by the presence of existing attribution keys in the snapshot.
     *
     * default: false
     */
    track?: boolean;
    /**
     * Provides a policy for how to track attribution data on segments.
     * This option must be provided if either:
     * - `track` is set to true
     * - a document containing existing attribution information is loaded
     */
    policyFactory?: () => AttributionPolicy;
}

/* Excluded from this release type: IMergeTreeClientSequenceArgs */

/**
 * @alpha
 */
export declare interface IMergeTreeDelta {
    /**
     * Type of this change.
     */
    type: MergeTreeDeltaType;
}

/**
 * @alpha
 */
export declare interface IMergeTreeDeltaCallbackArgs<TOperationType extends MergeTreeDeltaOperationTypes = MergeTreeDeltaOperationType> {
    readonly operation: TOperationType;
    readonly deltaSegments: IMergeTreeSegmentDelta[];
}

/**
 * @alpha
 */
export declare type IMergeTreeDeltaOp = IMergeTreeInsertMsg | IMergeTreeRemoveMsg | IMergeTreeAnnotateMsg | IMergeTreeObliterateMsg;

/**
 * @alpha
 */
export declare interface IMergeTreeDeltaOpArgs {
    /**
     * The group op which contains the operation
     * if there operation is part of a group op.
     */
    readonly groupOp?: IMergeTreeGroupMsg;
    /**
     * The merge tree operation
     */
    readonly op: IMergeTreeOp;
    /**
     * Get the sequence message, should only be null if the
     * Delta op args are for an unacked local change
     */
    readonly sequencedMessage?: ISequencedDocumentMessage;
    /**
     * If the operation is being applied as a stashed op, which means it may have been previously submitted, and therefore should not be resubmitted
     */
    readonly stashed?: boolean;
}

/**
 * @deprecated The ability to create group ops will be removed in an upcoming
 * release, as group ops are redundant with the native batching capabilities
 * of the runtime
 *
 * @alpha
 */
export declare interface IMergeTreeGroupMsg extends IMergeTreeDelta {
    type: typeof MergeTreeDeltaType.GROUP;
    ops: IMergeTreeDeltaOp[];
}

/**
 * @alpha
 */
export declare interface IMergeTreeInsertMsg extends IMergeTreeDelta {
    type: typeof MergeTreeDeltaType.INSERT;
    pos1?: number;
    relativePos1?: IRelativePosition;
    pos2?: number;
    relativePos2?: IRelativePosition;
    seg?: any;
}

/**
 * @alpha
 */
export declare interface IMergeTreeMaintenanceCallbackArgs extends IMergeTreeDeltaCallbackArgs<MergeTreeMaintenanceType> {
}

/**
 * @deprecated We no longer intend to support this functionality and it will
 * be removed in a future release. There is no replacement for this
 * functionality.
 * @alpha
 */
export declare interface IMergeTreeObliterateMsg extends IMergeTreeDelta {
    type: typeof MergeTreeDeltaType.OBLITERATE;
    pos1?: number;
    /**
     * This field is currently unused, but we keep it around to make the union
     * type of all merge-tree messages have the same fields
     */
    relativePos1?: never;
    pos2?: number;
    /**
     * This field is currently unused, but we keep it around to make the union
     * type of all merge-tree messages have the same fields
     */
    relativePos2?: never;
}

/**
 * @alpha
 */
export declare type IMergeTreeOp = IMergeTreeDeltaOp | IMergeTreeGroupMsg;

/**
 * @alpha
 */
export declare interface IMergeTreeOptions {
    catchUpBlobName?: string;
    /**
     * Whether or not reference positions can slide to special endpoint segments
     * denoting the positions immediately before the start and immediately after
     * the end of the string.
     *
     * This is primarily useful in the case of interval stickiness.
     */
    mergeTreeReferencesCanSlideToEndpoint?: boolean;
    mergeTreeSnapshotChunkSize?: number;
    /**
     * Whether to use the SnapshotV1 format over SnapshotLegacy.
     *
     * SnapshotV1 stores a view of the merge-tree at the current sequence number, preserving merge metadata
     * (e.g. clientId, seq, etc.) only for segment changes within the collab window.
     *
     * SnapshotLegacy stores a view of the merge-tree at the minimum sequence number along with the ops between
     * the minimum sequence number and the current sequence number.
     *
     * Both formats merge segments where possible (see {@link ISegment.canAppend})
     *
     * default: false
     *
     * @remarks
     * Despite the "legacy"/"V1" naming, both formats are actively used at the time of writing. SharedString
     * uses legacy and Matrix uses V1.
     */
    newMergeTreeSnapshotFormat?: boolean;
    /**
     * Options related to attribution
     */
    attribution?: IMergeTreeAttributionOptions;
    /**
     * Enables support for the obliterate operation -- a stronger form of remove
     * which deletes concurrently inserted segments
     *
     * Obliterate is currently experimental and may not work in all scenarios.
     *
     * Default value: false
     */
    mergeTreeEnableObliterate?: boolean;
}

/**
 * @alpha
 */
export declare interface IMergeTreeRemoveMsg extends IMergeTreeDelta {
    type: typeof MergeTreeDeltaType.REMOVE;
    pos1?: number;
    relativePos1?: IRelativePosition;
    pos2?: number;
    relativePos2?: IRelativePosition;
}

/**
 * @alpha
 */
export declare interface IMergeTreeSegmentDelta {
    segment: ISegment;
    propertyDeltas?: PropertySet;
}

/**
 * @deprecated This functionality was not meant to be exported and will be removed in a future release
 * @alpha
 */
export declare interface IMergeTreeTextHelper {
    getText(refSeq: number, clientId: number, placeholder: string, start?: number, end?: number): string;
}

/**
 * Tracks information about when and where this segment was moved to.
 *
 * Note that merge-tree does not currently support moving and only supports
 * obliterate. The fields below include "move" in their names to avoid renaming
 * in the future, when moves _are_ supported.
 * @alpha
 */
export declare interface IMoveInfo {
    /**
     * Local seq at which this segment was moved if the move is yet-to-be
     * acked.
     */
    localMovedSeq?: number;
    /**
     * The first seq at which this segment was moved.
     */
    movedSeq: number;
    /**
     * All seqs at which this segment was moved. In the case of overlapping,
     * concurrent moves this array will contain multiple seqs.
     *
     * The seq at  `movedSeqs[i]` corresponds to the client id at `movedClientIds[i]`.
     *
     * The first element corresponds to the seq of the first move
     */
    movedSeqs: number[];
    /**
     * A reference to the inserted destination segment corresponding to this
     * segment's move.
     *
     * If undefined, the move was an obliterate.
     *
     * Currently this field is unused, as we only support obliterate operations
     */
    moveDst?: ReferencePosition;
    /**
     * List of client IDs that have moved this segment.
     *
     * The client that actually moved the segment (i.e. whose move op was sequenced
     * first) is stored as the first client in this list. Other clients in the
     * list have all issued concurrent ops to move the segment.
     */
    movedClientIds: number[];
    /**
     * If this segment was inserted into a concurrently moved range and
     * the move op was sequenced before the insertion op. In this case,
     * the segment is visible only to the inserting client
     *
     * `wasMovedOnInsert` only applies for acked obliterates. That is, if
     * a segment inserted by a remote client is moved on insertion by a local
     * and unacked obliterate, we do not consider it as having been moved
     * on insert
     *
     * If a segment is moved on insertion, its length is only ever visible to
     * the client that inserted the segment. This is relevant in partial length
     * calculations
     */
    wasMovedOnInsert: boolean;
}

declare interface IOverlapClient {
    clientId: number;
    seglen: number;
}

/* Excluded from this release type: IRBAugmentation */

/* Excluded from this release type: IRBMatcher */

declare interface IRefsAtOffset {
    before?: DoublyLinkedList<LocalReference>;
    at?: DoublyLinkedList<LocalReference>;
    after?: DoublyLinkedList<LocalReference>;
}

/**
 * A position specified relative to a segment.
 * @alpha
 */
export declare interface IRelativePosition {
    /**
     * String identifier specifying a segment.
     */
    id?: string;
    /**
     * If true, insert before the specified segment.  If false or not defined,
     * insert after the specified segment.
     */
    before?: boolean;
    /**
     * A positive number \>= 1.  If before is false, offset is added to the position.
     * If before is true, offset is subtracted from the position.
     */
    offset?: number;
}

/**
 * Contains removal information associated to an {@link ISegment}.
 * @alpha
 */
export declare interface IRemovalInfo {
    /**
     * Local seq at which this segment was removed, if the removal is yet-to-be acked.
     */
    localRemovedSeq?: number;
    /**
     * Seq at which this segment was removed.
     */
    removedSeq: number;
    /**
     * List of client IDs that have removed this segment.
     * The client that actually removed the segment (i.e. whose removal op was sequenced first) is stored as the first
     * client in this list. Other clients in the list have all issued concurrent ops to remove the segment.
     * @remarks When this list has length \> 1, this is referred to as the "overlapping remove" case.
     */
    removedClientIds: number[];
}

declare interface IRootMergeBlock extends IMergeBlock {
    mergeTree?: MergeTree;
}

/**
 * A segment representing a portion of the merge tree.
 * Segments are leaf nodes of the merge tree and contain data.
 * @alpha
 */
export declare interface ISegment extends IMergeNodeCommon, Partial<IRemovalInfo>, Partial<IMoveInfo> {
    readonly type: string;
    readonly segmentGroups: SegmentGroupCollection;
    readonly trackingCollection: TrackingGroupCollection;
    /**
     * Whether or not this segment is a special segment denoting the start or
     * end of the tree
     *
     * Endpoint segments are imaginary segments positioned immediately before or
     * after the tree. These segments cannot be referenced by regular operations
     * and exist primarily as a bucket for local references to slide onto during
     * deletion of regular segments.
     */
    readonly endpointType?: "start" | "end";
    /**
     * The length of the contents of the node.
     */
    cachedLength: number;
    /**
     * Stores attribution keys associated with offsets of this segment.
     * This data is only persisted if MergeTree's `attributions.track` flag is set to true.
     * Pending segments (i.e. ones that only exist locally and haven't been acked by the server) also have
     * `attribution === undefined` until ack.
     *
     * Keys can be used opaquely with an IAttributor or a container runtime that provides attribution.
     * @remarks There are plans to make the shape of the data stored extensible in a couple ways:
     *
     * 1. Injection of custom attribution information associated with the segment (ex: copy-paste of
     * content but keeping the old attribution information).
     *
     * 2. Storage of multiple "channels" of information (ex: track property changes separately from insertion,
     * or only attribute certain property modifications, etc.)
     */
    attribution?: IAttributionCollection<AttributionKey>;
    /**
     * Manages pending local state for properties on this segment.
     */
    propertyManager?: PropertiesManager;
    /**
     * Local seq at which this segment was inserted.
     * This is defined if and only if the insertion of the segment is pending ack, i.e. `seq` is UnassignedSequenceNumber.
     * Once the segment is acked, this field is cleared.
     *
     * See {@link CollaborationWindow.localSeq} for more information on the semantics of localSeq.
     */
    localSeq?: number;
    /**
     * Local seq at which this segment was removed. If this is defined, `removedSeq` will initially be set to
     * UnassignedSequenceNumber. However, if another client concurrently removes the same segment, `removedSeq`
     * will be updated to the seq at which that client removed this segment.
     *
     * Like {@link ISegment.localSeq}, this field is cleared once the local removal of the segment is acked.
     * See {@link CollaborationWindow.localSeq} for more information on the semantics of localSeq.
     */
    localRemovedSeq?: number;
    /**
     * Seq at which this segment was inserted.
     * If undefined, it is assumed the segment was inserted prior to the collab window's minimum sequence number.
     */
    seq?: number;
    /**
     * Short clientId for the client that inserted this segment.
     */
    clientId: number;
    /**
     * Local references added to this segment.
     */
    localRefs?: LocalReferenceCollection;
    /**
     * Properties that have been added to this segment via annotation.
     */
    properties?: PropertySet;
    /**
     * Add properties to this segment via annotation.
     *
     * @remarks This function should not be called directly. Properties should
     * be added through the `annotateRange` functions.
     */
    addProperties(newProps: PropertySet, seq?: number, collaborating?: boolean, rollback?: PropertiesRollback): PropertySet;
    clone(): ISegment;
    canAppend(segment: ISegment): boolean;
    append(segment: ISegment): void;
    splitAt(pos: number): ISegment | undefined;
    toJSONObject(): any;
    /**
     * Acks the current segment against the segment group, op, and merge tree.
     *
     * @param segmentGroup - Pending segment group associated with this op.
     * @param opArgs - Information about the op that was acked
     * @returns `true` if the op modifies the segment, otherwise `false`.
     * The only current false case is overlapping remove, where a segment is removed
     * by a previously sequenced operation before the current operation is acked.
     * @throws - error if the segment state doesn't match segment group or op.
     * E.g. if the segment group is not first in the pending queue, or
     * an inserted segment does not have unassigned sequence number.
     */
    ack(segmentGroup: SegmentGroup, opArgs: IMergeTreeDeltaOpArgs): boolean;
}

/**
 * @alpha
 */
export declare interface ISegmentAction<TClientData> {
    (segment: ISegment, pos: number, refSeq: number, clientId: number, start: number, end: number, accum: TClientData): boolean;
}

/**
 * someday we may split tree leaves from segments, but for now they are the same
 * this is just a convenience type that makes it clear that we need something that is both a segment and a leaf node
 */
declare type ISegmentLeaf = ISegment & IMergeLeaf;

/* Excluded from this release type: isMergeTreeDeltaRevertible */

/**
 * @alpha
 */
export declare interface ITrackingGroup {
    tracked: readonly Trackable[];
    size: number;
    has(trackable: Trackable): boolean;
    link(trackable: Trackable): void;
    unlink(trackable: Trackable): boolean;
}

/* Excluded from this release type: KeyComparer */

declare interface ListNode<T> {
    readonly list: DoublyLinkedList<T> | undefined;
    readonly data: T;
    readonly next: ListNode<T> | undefined;
    readonly prev: ListNode<T> | undefined;
}

declare interface ListNodeRange<T> {
    first: ListNode<T>;
    last: ListNode<T>;
}

/* Excluded from this release type: LocalReference */

/**
 * Represents a collection of {@link LocalReferencePosition}s associated with
 * one segment in a merge-tree.
 * Represents a collection of {@link LocalReferencePosition}s associated with one segment in a merge-tree.
 * @alpha
 */
export declare class LocalReferenceCollection {
    /** Segment this `LocalReferenceCollection` is associated to. */
    private readonly segment;
    static append(seg1: ISegment, seg2: ISegment): void;
    private readonly refsByOffset;
    private refCount;
    /***/
    constructor(
    /** Segment this `LocalReferenceCollection` is associated to. */
    segment: ISegment, initialRefsByfOffset?: (IRefsAtOffset | undefined)[]);
    /**
     * @remarks This method should only be called by mergeTree.
     */
    [Symbol.iterator](): {
        next(): IteratorResult<LocalReferencePosition>;
        [Symbol.iterator](): any;
    };
    /**
     * @remarks This method should only be called by mergeTree.
     */
    get empty(): boolean;
    /**
     * @remarks This method should only be called by mergeTree.
     */
    createLocalRef(offset: number, refType: ReferenceType, properties: PropertySet | undefined, slidingPreference?: SlidingPreference, canSlideToEndpoint?: boolean): LocalReferencePosition;
    /**
     * @remarks This method should only be called by mergeTree.
     */
    addLocalRef(lref: LocalReferencePosition, offset: number): void;
    /**
     * @remarks This method should only be called by mergeTree.
     */
    removeLocalRef(lref: LocalReferencePosition): LocalReferencePosition | undefined;
    /**
     *
     * Called by 'append()' implementations to append local refs from the given 'other' segment to the
     * end of 'this' segment.
     *
     * Note: This method should be invoked after the caller has ensured that segments can be merged,
     * but before 'this' segment's cachedLength has changed, or the adjustment to the local refs
     * will be incorrect.
     *
     * @remarks This method should only be called by mergeTree.
     */
    append(other: LocalReferenceCollection): void;
    /**
     * Returns true of the local reference is in the collection, otherwise false.
     *
     * @remarks This method should only be called by mergeTree.
     */
    has(lref: ReferencePosition): boolean;
    /**
     * Splits this `LocalReferenceCollection` into the intervals [0, offset) and [offset, originalLength).
     * Local references in the former half of this split will remain associated with the segment used on construction.
     * Local references in the latter half of this split will be transferred to `splitSeg`,
     * and its `localRefs` field will be set.
     * @param offset - Offset into the original segment at which the collection should be split
     * @param splitSeg - Split segment which originally corresponded to the indices [offset, originalLength)
     * before splitting.
     *
     * @remarks This method should only be called by mergeTree.
     */
    split(offset: number, splitSeg: ISegment): void;
    /**
     * @remarks This method should only be called by mergeTree.
     */
    addBeforeTombstones(...refs: Iterable<LocalReferencePosition>[]): void;
    /**
     * @remarks This method should only be called by mergeTree.
     */
    addAfterTombstones(...refs: Iterable<LocalReferencePosition>[]): void;
    /**
     * @remarks This method should only be called by mergeTree.
     */
    isAfterTombstone(lref: LocalReferencePosition): boolean;
    /**
     * @remarks This method should only be called by mergeTree.
     */
    walkReferences(visitor: (lref: LocalReferencePosition) => boolean | void | undefined, start?: LocalReferencePosition, forward?: boolean): boolean;
}

/**
 * @sealed
 * @alpha
 */
export declare interface LocalReferencePosition extends ReferencePosition {
    callbacks?: Partial<Record<"beforeSlide" | "afterSlide", (ref: LocalReferencePosition) => void>>;
    readonly trackingCollection: TrackingGroupCollection;
    /**
     * Whether or not this reference position can slide onto one of the two
     * special segments representing the position before or after the tree
     */
    readonly canSlideToEndpoint?: boolean;
}

/* Excluded from this release type: LRUSegment */

/**
 * Any mapping from a string to values of type `T`
 * @alpha
 */
export declare interface MapLike<T> {
    [index: string]: T;
}

/**
 * Markers are a special kind of segment that do not hold any content.
 *
 * Markers with a reference type of {@link ReferenceType.Tile} support spatially
 * accelerated queries for finding the next marker to the left or right of it in
 * sub-linear time. This is useful, for example, in the case of jumping from the
 * start of a paragraph to the end, assuming a paragraph is bound by markers at
 * the start and end.
 *
 * @alpha
 */
export declare class Marker extends BaseSegment implements ReferencePosition, ISegment {
    refType: ReferenceType;
    static readonly type = "Marker";
    static is(segment: ISegment): segment is Marker;
    readonly type = "Marker";
    static make(refType: ReferenceType, props?: PropertySet): Marker;
    constructor(refType: ReferenceType);
    toJSONObject(): IJSONMarkerSegment;
    static fromJSONObject(spec: any): Marker | undefined;
    clone(): Marker;
    getSegment(): this;
    getOffset(): number;
    getProperties(): PropertySet | undefined;
    getId(): string | undefined;
    toString(): string;
    protected createSplitSegmentAt(pos: number): undefined;
    canAppend(segment: ISegment): boolean;
    append(): void;
}

/* Excluded from this release type: matchProperties */

/* Excluded from this release type: maxReferencePosition */

/* Excluded from this release type: MergeBlock */

/**
 * @alpha
 */
export declare class MergeNode implements IMergeNodeCommon {
    index: number;
    ordinal: string;
    cachedLength: number;
    isLeaf(): this is ISegment;
}

/* Excluded from this release type: MergeTree */

/* Excluded from this release type: MergeTreeDeltaCallback */

/**
 * @alpha
 */
export declare type MergeTreeDeltaOperationType = typeof MergeTreeDeltaType.ANNOTATE | typeof MergeTreeDeltaType.INSERT | typeof MergeTreeDeltaType.REMOVE | typeof MergeTreeDeltaType.OBLITERATE;

/**
 * @alpha
 */
export declare type MergeTreeDeltaOperationTypes = MergeTreeDeltaOperationType | MergeTreeMaintenanceType;

/* Excluded from this release type: MergeTreeDeltaRevertible */

/**
 * @alpha
 */
export declare const MergeTreeDeltaType: {
    readonly INSERT: 0;
    readonly REMOVE: 1;
    readonly ANNOTATE: 2;
    /**
     * @deprecated The ability to create group ops will be removed in an upcoming release, as group ops are redundant with he native batching capabilities of the runtime
     */
    readonly GROUP: 3;
    readonly OBLITERATE: 4;
};

/**
 * @alpha
 */
export declare type MergeTreeDeltaType = (typeof MergeTreeDeltaType)[keyof typeof MergeTreeDeltaType];

/* Excluded from this release type: MergeTreeMaintenanceCallback */

/**
 * Enum-like constant defining the types of "maintenance" events on a merge tree.
 * Maintenance events correspond to structural segment changes or acks of pending segments.
 *
 * Note: these values are assigned negative integers to avoid clashing with `MergeTreeDeltaType`.
 * @alpha
 */
export declare const MergeTreeMaintenanceType: {
    /**
     * Notification that a segment "append" has occurred, i.e. two adjacent segments have been merged.
     * BEWARE: `deltaSegments` on the corresponding event will contain both the merged segment and the latter
     * segment, pre-merge.
     * For example, if the merge tree originally had two adjacent segments [A][B] and called A.append(B) to get
     * segment [AB], `deltaSegments` would contain [AB] and [B].
     */
    readonly APPEND: -1;
    /**
     * Notification that a segment has been split in two.
     * `deltaSegments` on the corresponding event will contain the resulting two segments.
     */
    readonly SPLIT: -2;
    /**
     * Notification that a segment has been unlinked (i.e. removed) from the MergeTree.
     * This occurs on leaf segments during Zamboni when the segment's tracking collection is empty
     * (e.g., not being tracked for undo/redo).
     * It also occurs on internal merge tree segments when re-packing children to maintain tree balancing invariants.
     */
    readonly UNLINK: -3;
    /**
     * Notification that a local change has been acknowledged by the server.
     * This means that it has made the round trip to the server and has had a sequence number assigned.
     */
    readonly ACKNOWLEDGED: -4;
};

/**
 * @alpha
 */
export declare type MergeTreeMaintenanceType = (typeof MergeTreeMaintenanceType)[keyof typeof MergeTreeMaintenanceType];

/**
 * @alpha
 */
export declare interface MergeTreeRevertibleDriver {
    insertFromSpec(pos: number, spec: IJSONSegment): void;
    removeRange(start: number, end: number): void;
    annotateRange(start: number, end: number, props: PropertySet): void;
}

/* Excluded from this release type: minReferencePosition */

/**
 * Tracks length information for a part of a MergeTree (block) at a given time (seq).
 * These objects are associated with internal nodes (i.e. blocks).
 */
declare interface PartialSequenceLength {
    /**
     * Sequence number
     */
    seq: number;
    /**
     * The length of the associated block.
     */
    len: number;
    /**
     * The delta between the current length of the associated block and its length at the previous seq number.
     */
    seglen: number;
    /**
     * clientId for the client that submitted the op with sequence number `seq`.
     */
    clientId?: number;
    /**
     * If this partial length obliterated remote segments, this is the length of
     * those segments
     */
    remoteObliteratedLen?: number;
    /**
     * This field maps each client to the size of the intersection between segments deleted at this seq
     * and segments concurrently deleted by that client.
     *
     * For example, this PartialSequenceLength:
     * ```typescript
     * {
     *     seq: 5,
     *     len: 100,
     *     seglen: -10,
     *     clientId: 0,
     *     overlapRemoveClients: <RedBlack tree with key-values expressed by>{
     *         1: { clientId: 1, seglen: -5 },
     *         3: { clientId: 3, seglen: -10 }
     *     }
     * }
     * ```
     *
     * corresponds to an op submitted by client 0 which:
     * - reduces the length of this block by 10 (it may have deleted a single segment of length 10,
     *     several segments totalling length 10, or even delete and add content for a total reduction of 10 length)
     * - was concurrent to one or more ops submitted by client 1 that also removed some of the same segments,
     *     whose length totalled 5
     * - was concurrent to one or more ops submitted by client 3 that removed some of the same segments,
     *     whose length totalled 10
     */
    overlapRemoveClients?: RedBlackTree<number, IOverlapClient>;
    /**
     * This field is the same as `overlapRemoveClients`, except that it tracks
     * overlapping obliterates rather than removes.
     */
    overlapObliterateClients?: RedBlackTree<number, IOverlapClient>;
}

/**
 * Keeps track of partial sums of segment lengths for all sequence numbers in the current collaboration window.
 * Only used during active collaboration.
 *
 * This class is associated with an internal node (block) of a MergeTree. It efficiently answers queries of the form
 * "What is the length of `block` from the perspective of some particular seq and clientId?".
 *
 * It also supports incremental updating of state for newly-sequenced ops that don't affect the structure of the
 * MergeTree.
 *
 * To answer these queries, it pre-builds several lists which track the length of the block at a per-sequence-number
 * level. These lists are:
 *
 * 1. (`partialLengths`): Stores the total length of the block.
 * 2. (`clientSeqNumbers[clientId]`): Stores only the total lengths of segments submitted by `clientId`. [see footnote]
 *
 * The reason both lists are necessary is that resolving the length of the block from the perspective of
 * (clientId, refSeq) requires including both of the following types of segments:
 * 1. Segments sequenced before `refSeq`
 * 2. Segments submitted by `clientId`
 *
 * This is possible with the above bookkeeping, using:
 *
 * (length of the block at the minimum sequence number)
 * + (partialLengths total length at refSeq)
 * + (clientSeqNumbers total length at most recent op)
 * - (clientSeqNumbers total length at refSeq)
 *
 * where the subtraction avoids double-counting segments submitted by clientId sequenced within the collab window.
 *
 * To enable reconnect, if constructed with `computeLocalPartials === true` it also supports querying for the length of
 * the block from the perspective of the local client at a particular `refSeq` and `localSeq`. This computation is
 * similar to the above:
 *
 * (length of the block at the minimum sequence number)
 * + (partialLengths total length at refSeq)
 * + (unsequenced edits' total length submitted before localSeq)
 * - (overlapping remove of the unsequenced edits' total length at refSeq)
 *
 * This algorithm scales roughly linearly with number of editing clients and the size of the collab window.
 * (certain unlikely sequences of operations may introduce log factors on those variables)
 *
 * Note: there is some slight complication with clientSeqNumbers resulting from the possibility of different clients
 * concurrently removing the same segment. See the field's documentation for more details.
 */
declare class PartialSequenceLengths {
    /**
     * The minimumSequenceNumber as defined by the collab window used in the last call to `update`,
     * or if no such calls have been made, the one used on construction.
     */
    minSeq: number;
    static options: PartialSequenceLengthsOptions;
    /**
     * Combine the partial lengths of block's children
     * @param block - an interior node. If `recur` is false, it is assumed that each interior node child of this block
     * has its partials up to date.
     * @param collabWindow - segment window of the segment tree containing `block`.
     * @param recur - whether to recursively compute partial lengths for internal children of `block`.
     * This incurs more work, but gives correct bookkeeping in the case that a descendant in the merge tree has been
     * modified without bubbling up the resulting partial length change to this block's partials.
     * @param computeLocalPartials - whether to compute partial length information about local unsequenced ops.
     * This enables querying for the length of the block at a given localSeq, but incurs extra work.
     * Local partial information doesn't support `update`.
     */
    static combine(block: IMergeBlock, collabWindow: CollaborationWindow, recur?: boolean, computeLocalPartials?: boolean): PartialSequenceLengths;
    /**
     * @returns a PartialSequenceLengths structure which tracks only lengths of leaf children of the provided
     * IMergeBlock.
     */
    private static fromLeaves;
    private static getOverlapClients;
    private static accumulateRemoveClientOverlap;
    private static accumulateMoveClientOverlap;
    /**
     * Coalesce overlapping move lengths for a partial length entry that already
     * exists
     *
     * @param segmentLen - Length of segment with overlapping moves
     * @param segment - Segment with overlapping moves
     * @param firstGte - Existing partial length entry
     * @param clientIds - Ids of clients that concurrently obliterated this segment
     */
    static accumulateMoveOverlapForExisting(segmentLen: number, segment: ISegment, firstGte: PartialSequenceLength, clientIds: number[]): void;
    /**
     * @param obliterateOverlapLen - Length of segment with overlap
     * @param clientIds - Ids of clients that have concurrently obliterated this
     * segment
     */
    private static getMoveOverlapForExisting;
    private static updatePartialsAfterInsertion;
    /**
     * Inserts length information about the insertion of `segment` into
     * `combinedPartialLengths.partialLengths`.
     *
     * Does not update the clientSeqNumbers field to account for this segment.
     *
     * If `removalInfo` or `moveInfo` are defined, this operation updates the
     * bookkeeping to account for the (re)moval of this segment at the (re)movedSeq
     * instead.
     *
     * When the insertion or (re)moval of the segment is un-acked and
     * `combinedPartialLengths` is meant to compute such records, this does the
     * analogous addition to the bookkeeping for the local segment in
     * `combinedPartialLengths.unsequencedRecords`.
     */
    private static insertSegment;
    private static addSeq;
    /**
     * Length of the block this PartialSequenceLength corresponds to when viewed at `minSeq`.
     */
    private minLength;
    /**
     * Total number of segments in the subtree rooted at the block this PartialSequenceLength corresponds to.
     */
    private segmentCount;
    /**
     * List of PartialSequenceLength objects--ordered by increasing seq--giving length information about
     * the block associated with this PartialSequenceLengths object.
     *
     * `partialLengths[i].len` contains the length of this block considering only sequenced segments with
     * `sequenceNumber <= partialLengths[i].seq`.
     */
    private readonly partialLengths;
    /**
     * clientSeqNumbers[clientId] is a list of partial lengths for sequenced ops which either:
     * - were submitted by `clientId`.
     * - deleted a range containing segments that were concurrently deleted by `clientId`
     *
     * The second case is referred to as the "overlapping delete" case. It is necessary to avoid double-counting
     * the removal of those segments in queries including clientId.
     */
    private readonly clientSeqNumbers;
    /**
     * Contains information required to answer queries for the length of this segment from the perspective of
     * the local client but not including all local segments (i.e., `localSeq !== collabWindow.localSeq`).
     * This field is only computed if requested in the constructor (i.e. `computeLocalPartials === true`).
     */
    private unsequencedRecords;
    constructor(
    /**
     * The minimumSequenceNumber as defined by the collab window used in the last call to `update`,
     * or if no such calls have been made, the one used on construction.
     */
    minSeq: number, computeLocalPartials: boolean);
    update(node: IMergeBlock, seq: number, clientId: number, collabWindow: CollaborationWindow): void;
    /**
     * Returns the length of this block as viewed from the perspective of `clientId` at `refSeq`.
     * This is the total length of all segments sequenced at or before refSeq OR submitted by `clientId`.
     * If `clientId` is the local client, `localSeq` can also be provided. In that case, it is the total
     * length of all segments submitted at or before `refSeq` in addition to any local, unacked segments
     * with `segment.localSeq <= localSeq`.
     *
     * Note: the local case (where `localSeq !== undefined`) is only supported on a PartialSequenceLength object
     * constructed with `computeLocalPartials` set to true and not subsequently updated with `update`.
     */
    getPartialLength(refSeq: number, clientId: number, localSeq?: number): number;
    /**
     * Computes the seglen for the double-counted removed overlap at (refSeq, localSeq). This logic is equivalent
     * to the following:
     *
     * ```typescript
     *   let total = 0;
     *   for (const partialLength of this.unsequencedRecords!.overlappingRemoves) {
     *       if (partialLength.seq > refSeq) {
     *           break;
     *       }
     *
     *      if (partialLength.localSeq <= localSeq) {
     *          total += partialLength.seglen;
     *      }
     *   }
     *
     *   return total;
     * ```
     *
     * Reconnect happens to only need to compute these lengths for two refSeq values: before and
     * after the rebase. Since these lists potentially scale with O(collab window * number of local edits)
     * and potentially need to be queried for each local op that gets rebased,
     * we cache the results for a given refSeq in `this.unsequencedRecords.cachedOverlappingByRefSeq` so
     * that they can be binary-searched the same way the usual partialLengths lists are.
     */
    private computeOverlappingLocalRemoves;
    toString(glc?: (id: number) => string, indentCount?: number): string;
    private zamboni;
    private addClientSeqNumber;
    private addClientSeqNumberFromPartial;
    private cliLatestLEQ;
    private cliLatest;
}

declare interface PartialSequenceLengthsOptions {
    verifier?: (partialLengths: PartialSequenceLengths) => void;
    verifyExpected?: (mergeTree: MergeTree, node: IMergeBlock, refSeq: number, clientId: number, localSeq?: number) => void;
    zamboni: boolean;
}

/**
 * @alpha
 */
export declare class PropertiesManager {
    private pendingKeyUpdateCount;
    ackPendingProperties(annotateOp: IMergeTreeAnnotateMsg): void;
    private decrementPendingCounts;
    addProperties(oldProps: PropertySet, newProps: PropertySet, seq?: number, collaborating?: boolean, rollback?: PropertiesRollback): PropertySet;
    copyTo(oldProps: PropertySet, newProps: PropertySet | undefined, newManager: PropertiesManager): PropertySet | undefined;
    hasPendingProperties(): boolean;
    hasPendingProperty(key: string): boolean;
}

/**
 * @alpha
 */
export declare enum PropertiesRollback {
    /** Not in a rollback */
    None = 0,
    /** Rollback */
    Rollback = 1
}

/* Excluded from this release type: Property */

/* Excluded from this release type: PropertyAction */

/**
 * A loosely-typed mapping from strings to any value.
 *
 * @remarks Property sets are expected to be JSON-stringify-able.
 *
 * @privateRemarks PropertySet is typed using `any` because when you include
 * custom methods such as toJSON(), JSON.stringify accepts most types other than
 * functions
 * @alpha
 */
export declare type PropertySet = MapLike<any>;

/* Excluded from this release type: QProperty */

/* Excluded from this release type: RBColor */

/* Excluded from this release type: RBNode */

/* Excluded from this release type: RBNodeActions */

/* Excluded from this release type: RedBlackTree */

/**
 * Represents a reference to a place within a merge tree. This place conceptually remains stable over time
 * by referring to a particular segment and offset within that segment.
 * Thus, this reference's character position changes as the tree is edited.
 * @alpha
 */
export declare interface ReferencePosition {
    /**
     * Properties associated with this reference
     */
    properties?: PropertySet;
    /**
     * The direction for this reference position to slide when the segment it
     * points to is removed. See {@link (SlidingPreference:type)} for additional context.
     *
     * Defaults to SlidingPreference.Forward
     */
    slidingPreference?: SlidingPreference;
    refType: ReferenceType;
    /**
     * Gets the segment that this reference position is semantically associated with. Returns undefined iff the
     * reference became detached from the string.
     */
    getSegment(): ISegment | undefined;
    /**
     * Gets the offset for this reference position within its associated segment.
     *
     * @example
     *
     * If a merge-tree has 3 leaf segments ["hello", " ", "world"] and a ReferencePosition refers to the "l"
     * in "world", that reference's offset would be 3 as "l" is the character at index 3 within "world".
     */
    getOffset(): number;
    /**
     * @param newProps - Properties to add to this reference.
     * @remarks Note that merge-tree does not broadcast changes to other clients. It is up to the consumer
     * to ensure broadcast happens if that is desired.
     */
    addProperties(newProps: PropertySet): void;
    isLeaf(): this is ISegment;
}

/**
 * Flags enum that dictates behavior of a {@link ReferencePosition}
 * @alpha
 */
export declare enum ReferenceType {
    Simple = 0,
    /**
     * Allows this reference to be located using the `findTile` API on merge-tree.
     */
    Tile = 1,
    /**
     * Denotes that this reference begins the start of an interval. This is
     * generally not meaningful outside the context of interval collections
     * on SharedString.
     */
    RangeBegin = 16,
    /**
     * Denotes that this reference is the end of an interval. This is
     * generally not meaningful outside the context of interval collections
     * on SharedString.
     */
    RangeEnd = 32,
    /**
     * When a segment is marked removed (locally or with ack), this reference will slide to the first
     * valid option of:
     * 1. the start of the next furthest segment
     * 2. the end of the next nearest segment
     * 3. DetachedReferencePosition
     */
    SlideOnRemove = 64,
    /**
     * When a segment is marked removed (locally or with ack), this reference will remain on that segment.
     */
    StayOnRemove = 128,
    /**
     * Specifies that the reference position should never be added to the segment it refers to.
     * This is useful for comparison/iteration purposes
     */
    Transient = 256
}

/* Excluded from this release type: refGetTileLabels */

/* Excluded from this release type: refHasTileLabel */

/* Excluded from this release type: refHasTileLabels */

/* Excluded from this release type: refTypeIncludesFlag */

/* Excluded from this release type: reservedMarkerIdKey */

/* Excluded from this release type: reservedMarkerSimpleTypeKey */

/* Excluded from this release type: reservedRangeLabelsKey */

/* Excluded from this release type: reservedTileLabelsKey */

/* Excluded from this release type: revertMergeTreeDeltaRevertibles */

/**
 * @deprecated This functionality was not meant to be exported and will be removed in a future release
 * @alpha
 */
export declare interface SegmentGroup {
    segments: ISegmentLeaf[];
    previousProps?: PropertySet[];
    localSeq?: number;
    refSeq: number;
}

/**
 * @alpha
 */
export declare class SegmentGroupCollection {
    private readonly segment;
    private readonly segmentGroups;
    constructor(segment: ISegment);
    get size(): number;
    get empty(): boolean;
    enqueue(segmentGroup: SegmentGroup): void;
    dequeue(): SegmentGroup | undefined;
    remove?(segmentGroup: SegmentGroup): boolean;
    pop?(): SegmentGroup | undefined;
    copyTo(segment: ISegment): void;
    private enqueueOnCopy;
}

/**
 * @alpha
 */
export declare interface SequenceOffsets {
    /**
     * Parallel array with posBreakpoints which tracks the seq of insertion.
     *
     * @example
     *
     * If seqs is [45, 46] and posBreakpoints is [0, 3], the section of the string
     * between offsets 0 and 3 was inserted at seq 45 and the section of the string between
     * 3 and the length of the string was inserted at seq 46.
     *
     * @remarks We use null here rather than undefined as round-tripping through JSON converts
     * undefineds to null anyway
     */
    seqs: (number | AttributionKey | null)[];
    posBreakpoints: number[];
}

/**
 * @alpha
 */
export declare interface SerializedAttributionCollection extends SequenceOffsets {
    channels?: {
        [name: string]: SequenceOffsets;
    };
    length: number;
}

/**
 * Dictates the preferential direction for a {@link ReferencePosition} to slide
 * in a merge-tree
 * @alpha
 */
export declare const SlidingPreference: {
    /**
     * Prefer sliding towards the start of the tree
     */
    readonly BACKWARD: 0;
    /**
     * Prefer sliding towards the end of the tree
     */
    readonly FORWARD: 1;
};

/**
 * Dictates the preferential direction for a {@link ReferencePosition} to slide
 * in a merge-tree
 * @alpha
 */
export declare type SlidingPreference = (typeof SlidingPreference)[keyof typeof SlidingPreference];

/* Excluded from this release type: SortedDictionary */

/* Excluded from this release type: SortedSegmentSet */

/* Excluded from this release type: SortedSegmentSetItem */

/* Excluded from this release type: SortedSet */

/**
 * The position immediately prior to the start of the tree
 */
declare class StartOfTreeSegment extends BaseEndpointSegment implements ISegment, IRemovalInfo {
    type: string;
    readonly endpointType = "start";
    /**
     * this segment pretends to be a sibling of the first real segment.
     * so compute the necessary properties to pretend to be that segment.
     */
    protected endpointSegmentProps(): {
        parent: IMergeBlock;
        index: number;
        depth: number;
    };
    get ordinal(): string;
}

/**
 * @alpha
 */
export declare class TextSegment extends BaseSegment {
    text: string;
    static readonly type = "TextSegment";
    readonly type = "TextSegment";
    static is(segment: ISegment): segment is TextSegment;
    static make(text: string, props?: PropertySet): TextSegment;
    static fromJSONObject(spec: any): TextSegment | undefined;
    constructor(text: string);
    toJSONObject(): IJSONTextSegment | string;
    clone(start?: number, end?: number): TextSegment;
    canAppend(segment: ISegment): boolean;
    toString(): string;
    append(segment: ISegment): void;
    protected createSplitSegmentAt(pos: number): TextSegment | undefined;
}

/* Excluded from this release type: toRemovalInfo */

/**
 * @alpha
 */
export declare type Trackable = ISegment | LocalReferencePosition;

/**
 * @alpha
 */
export declare class TrackingGroup implements ITrackingGroup {
    private readonly trackedSet;
    constructor();
    get tracked(): readonly Trackable[];
    get size(): number;
    has(trackable: Trackable): boolean;
    link(trackable: Trackable): void;
    unlink(trackable: Trackable): boolean;
}

/**
 * A collection of {@link ITrackingGroup}.
 * @alpha
 */
export declare class TrackingGroupCollection {
    private readonly trackable;
    private readonly _trackingGroups;
    get trackingGroups(): Set<TrackingGroup>;
    constructor(trackable: Trackable);
    link(trackingGroup: ITrackingGroup): void;
    unlink(trackingGroup: ITrackingGroup): boolean;
    copyTo(trackable: Trackable): void;
    get empty(): boolean;
    matches(trackingCollection: TrackingGroupCollection): boolean;
}

/* Excluded from this release type: UnassignedSequenceNumber */

/* Excluded from this release type: UniversalSequenceNumber */

export { }
