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 */

/* Excluded from this release type: AttributionKey */

/* Excluded from this release type: AttributionPolicy */

/**
 * 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;
}

/* Excluded from this release type: BaseSegment */

/* Excluded from this release type: Client */

/* Excluded from this release type: CollaborationWindow */

/* 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 */

/* Excluded from this release type: IAttributionCollection */

/* Excluded from this release type: IAttributionCollectionSerializer */

/* Excluded from this release type: IAttributionCollectionSpec */

/* Excluded from this release type: IChannelStorageService */

/* Excluded from this release type: IClientEvents */

/* Excluded from this release type: IEventThisPlaceHolder */

/* Excluded from this release type: IFluidDataStoreRuntime */

/* Excluded from this release type: IFluidHandle */

/* Excluded from this release type: IFluidSerializer */

/* Excluded from this release type: IHierBlock */

/* Excluded from this release type: IJSONMarkerSegment */

/* Excluded from this release type: IJSONSegment */

/* Excluded from this release type: IJSONTextSegment */

/* Excluded from this release type: IMarkerDef */

/* Excluded from this release type: IMergeBlock */

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

declare type IMergeNode = IMergeBlock | IMergeLeaf;

/* Excluded from this release type: IMergeNodeCommon */

/* Excluded from this release type: IMergeTreeAnnotateMsg */

/* Excluded from this release type: IMergeTreeAttributionOptions */

/* Excluded from this release type: IMergeTreeClientSequenceArgs */

/* Excluded from this release type: IMergeTreeDelta */

/* Excluded from this release type: IMergeTreeDeltaCallbackArgs */

/* Excluded from this release type: IMergeTreeDeltaOp */

/* Excluded from this release type: IMergeTreeDeltaOpArgs */

/* Excluded from this release type: IMergeTreeGroupMsg */

/* Excluded from this release type: IMergeTreeInsertMsg */

/* Excluded from this release type: IMergeTreeMaintenanceCallbackArgs */

/* Excluded from this release type: IMergeTreeObliterateMsg */

/* Excluded from this release type: IMergeTreeOp */

/* Excluded from this release type: IMergeTreeOptions */

/* Excluded from this release type: IMergeTreeRemoveMsg */

/* Excluded from this release type: IMergeTreeSegmentDelta */

/* Excluded from this release type: IMergeTreeTextHelper */

/* Excluded from this release type: IMoveInfo */

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>;
}

/* Excluded from this release type: IRelativePosition */

/* Excluded from this release type: IRemovalInfo */

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

/* Excluded from this release type: ISegment */

/* Excluded from this release type: ISegmentAction */

/**
 * 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 */

/* Excluded from this release type: ISummaryTreeWithStats */

/* Excluded from this release type: ITelemetryLoggerExt */

/* Excluded from this release type: ITrackingGroup */

/* 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 */

/* Excluded from this release type: LocalReferenceCollection */

/* Excluded from this release type: LocalReferencePosition */

/* Excluded from this release type: LRUSegment */

/* Excluded from this release type: MapLike */

/* Excluded from this release type: Marker */

/* Excluded from this release type: matchProperties */

/* Excluded from this release type: maxReferencePosition */

/* Excluded from this release type: MergeBlock */

/* Excluded from this release type: MergeNode */

/* Excluded from this release type: MergeTree */

/* Excluded from this release type: MergeTreeDeltaCallback */

/* Excluded from this release type: MergeTreeDeltaOperationType */

/* Excluded from this release type: MergeTreeDeltaOperationTypes */

/* Excluded from this release type: MergeTreeDeltaRevertible */

/* Excluded from this release type: MergeTreeDeltaType */

/* Excluded from this release type: MergeTreeMaintenanceCallback */

/* Excluded from this release type: MergeTreeMaintenanceType */

/* Excluded from this release type: MergeTreeRevertibleDriver */

/* 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;
}

/* Excluded from this release type: PropertiesManager */

/* Excluded from this release type: PropertiesRollback */

/* Excluded from this release type: Property */

/* Excluded from this release type: PropertyAction */

/* Excluded from this release type: PropertySet */

/* 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 */

/* Excluded from this release type: ReferencePosition */

/* Excluded from this release type: ReferenceType */

/* 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 */

/* Excluded from this release type: SegmentGroup */

/* Excluded from this release type: SegmentGroupCollection */

/* Excluded from this release type: SequenceOffsets */

/* Excluded from this release type: SerializedAttributionCollection */

/* Excluded from this release type: 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;
}

/* Excluded from this release type: TextSegment */

/* Excluded from this release type: toRemovalInfo */

/* Excluded from this release type: Trackable */

/* Excluded from this release type: TrackingGroup */

/* Excluded from this release type: TrackingGroupCollection */

/* Excluded from this release type: TypedEventEmitter */

/* Excluded from this release type: UnassignedSequenceNumber */

/* Excluded from this release type: UniversalSequenceNumber */

export { }
