/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { ISegmentInternal, ISegmentPrivate, MergeBlock, type ObliterateInfo } from "./mergeTreeNodes.js";
import type { InsertOperationStamp, OperationStamp, RemoveOperationStamp } from "./stamps.js";
export interface StringToType {
    "string": string;
    "number": number;
    "object": object;
    "array": unknown[];
    "boolean": boolean;
}
export declare function propExists<P extends string>(thing: unknown, prop: P): thing is Record<P, unknown>;
export declare function hasProp<P extends string, T extends keyof StringToType>(thing: unknown, prop: P, type: T): thing is Record<P, StringToType[typeof type]>;
export declare function propInstanceOf<P extends string, T>(thing: unknown, prop: P, type: new (...args: any[]) => T): thing is Record<P, T>;
/**
 * Contains insertion information associated to an {@link ISegment}.
 */
export interface IHasInsertionInfo {
    insert: InsertOperationStamp;
}
export interface ISegmentInsideObliterateInfo {
    /**
     * Populated iff this segment was inserted into a range affected by concurrent obliterates at the time of its insertion.
     * Contains information about the 'most recent' (i.e. 'winning' in the sense below) obliterate.
     *
     * BEWARE: We have opted for a certain form of last-write wins (LWW) semantics for obliterates:
     * the client which last obliterated a range is considered to have "won ownership" of that range and may insert into it
     * without that insertion being obliterated by other clients' concurrent obliterates.
     *
     * Therefore, this field can be populated even if the segment has not been obliterated (i.e. is still visible).
     * This happens precisely when the segment was inserted by the same client that 'won' the obliterate (in a scenario where
     * a client first issues a sided obliterate impacting a range, then inserts into that range before the server has acked the obliterate).
     *
     * See the test case "obliterate with mismatched final states" for an example of such a scenario.
     *
     * TODO:AB#29553: This property is not persisted in the V1 summary, but it should be.
     */
    obliteratePrecedingInsertion?: ObliterateInfo;
    /**
     * Populated iff this segment was inserted into a range concurrently removed by a local obliterate operation.
     * This field is unset once the newest such overlapping obliterate is acked, and allows recomputing {@link obliteratePrecedingInsertion}
     * if that local obliterate is resubmitted.
     *
     * TODO:AB#29553: This property is not persisted in the V1 summary, but it should be.
     */
    insertionRefSeqStamp?: OperationStamp;
}
/**
 * Converts a segment-like object to an insertion info object if possible.
 *
 * @param segmentLike - The segment-like object to convert.
 * @returns The insertion info object if the conversion is possible, otherwise undefined.
 */
export declare const toInsertionInfo: (segmentLike: unknown) => IHasInsertionInfo | undefined;
/**
 * A type-guard which determines if the segment has insertion info, and
 * returns true if it does, along with applying strong typing.
 *
 * @param segmentLike - The segment-like object to check.
 * @returns True if the segment has insertion info, otherwise false.
 */
export declare const isInserted: (segmentLike: unknown) => segmentLike is IHasInsertionInfo;
export declare const isInsideObliterate: (segmentLike: unknown) => segmentLike is ISegmentInsideObliterateInfo;
/**
 * Asserts that the segment has insertion info. Usage of this function should not produce a user facing error.
 *
 * @param segmentLike - The segment-like object to check.
 * @throws Will throw an error if the segment does not have insertion info.
 */
export declare const assertInserted: <T extends Partial<IHasInsertionInfo> | undefined>(segmentLike: ISegmentInternal | Partial<IHasInsertionInfo> | T) => asserts segmentLike is IHasInsertionInfo | Exclude<T, Partial<IHasInsertionInfo>>;
/**
 * Common properties for a node in a merge tree.
 */
export interface IMergeNodeInfo {
    /**
     * The parent merge block if the node is parented
     */
    parent: MergeBlock;
    /**
     * 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;
}
/**
 * Converts a segment-like object to a merge node info object if possible.
 *
 * @param segmentLike - The segment-like object to convert.
 * @returns The merge node info object if the conversion is possible, otherwise undefined.
 */
export declare const toMergeNodeInfo: (nodeLike: unknown) => IMergeNodeInfo | undefined;
/**
 * A type-guard which determines if the segment has merge node info, and
 * returns true if it does, along with applying strong typing.
 *
 * @param nodeLike - The segment-like object to check.
 * @returns True if the segment has merge node info, otherwise false.
 */
export declare const isMergeNodeInfo: (nodeLike: unknown) => nodeLike is IMergeNodeInfo;
/**
 * Asserts that the segment has merge node info. Usage of this function should not produce a user facing error.
 *
 * @param segmentLike - The segment-like object to check.
 * @throws Will throw an error if the segment does not have merge node info.
 */
export declare const assertMergeNode: <T extends Partial<IMergeNodeInfo> | undefined>(nodeLike: ISegmentInternal | ISegmentPrivate | Partial<IMergeNodeInfo> | T) => asserts nodeLike is IMergeNodeInfo | Exclude<T, Partial<IMergeNodeInfo>>;
/**
 * Removes the merge node info. This is used to remove nodes from the merge-tree.
 * @param segmentLike - The segment-like object to check.
 * @returns This function will change the type of the provided node like to never via an assertion. This
 * ensures no further usage of the removed merge node info is allowed. if continued use is required other
 * type coercion methods should be used to correctly re-type the variable.
 */
export declare const removeMergeNodeInfo: (nodeLike: IMergeNodeInfo) => asserts nodeLike is never;
/**
 * Contains removal information associated with an {@link ISegment}.
 *
 * Segments can be removed concurrently by multiple clients.
 */
export interface IHasRemovalInfo {
    /**
     * Operation stamps which have removed this segment. This list is sorted by stamp order, where removes[0] is the earliest removal.
     */
    removes: RemoveOperationStamp[];
}
/**
 * Converts a segment-like object to a removal info object if possible.
 *
 * @param segmentLike - The segment-like object to convert.
 * @returns The removal info object if the conversion is possible, otherwise undefined.
 */
export declare const toRemovalInfo: (segmentLike: unknown) => IHasRemovalInfo | undefined;
/**
 * A type-guard which determines if the segment has removal info, and
 * returns true if it does, along with applying strong typing.
 *
 * @param segmentLike - The segment-like object to check.
 * @returns True if the segment has removal info, otherwise false.
 */
export declare const isRemoved: (segmentLike: unknown) => segmentLike is IHasRemovalInfo;
/**
 * Asserts that the segment has removal info. Usage of this function should not produce a user facing error.
 *
 * @param segmentLike - The segment-like object to check.
 * @throws Will throw an error if the segment does not have removal info.
 */
export declare const assertRemoved: <T extends Partial<IHasRemovalInfo> | undefined>(segmentLike: ISegmentInternal | Partial<IHasRemovalInfo> | T) => asserts segmentLike is IHasRemovalInfo | Exclude<T, Partial<IHasRemovalInfo>>;
/**
 * Removes the removal info. This is used in rollback.
 * @param segmentLike - The segment-like object to check.
 * @returns This function will change the type of the provided node like to never via an assertion. This
 * ensures no further usage of the removed removal info is allowed. if continued use is required other
 * type coercion methods should be use to correctly re-type the variable.
 */
export declare const removeRemovalInfo: (nodeLike: IHasRemovalInfo) => asserts nodeLike is Record<keyof IHasRemovalInfo, never>;
/**
 * Returns whether this segment was marked removed as soon as its insertion was acked.
 *
 * This can happen when an an insert occurs concurrent to an obliterate over the range the segment was inserted into,
 * and the obliterate was sequenced first.
 *
 * When this happens, the segment is only ever visible to the client that inserted the segment
 * (and only until that client has seen the obliterate which removed their segment).
 */
export declare function wasRemovedOnInsert(segment: IHasInsertionInfo & ISegmentPrivate): boolean;
/**
 * A union type representing any segment info.
 */
export type SegmentInfo = IMergeNodeInfo | IHasInsertionInfo | IHasRemovalInfo | ISegmentInsideObliterateInfo;
/**
 * A type representing a segment with additional info.
 */
export type SegmentWithInfo<T extends SegmentInfo, S extends ISegmentPrivate = ISegmentPrivate> = S & T;
/**
 * Overwrites the segment info on a segment-like object.
 *
 * @param segmentLike - The segment-like object to set the info on.
 * @param info - The segment info to overwrite.
 * @returns The segment-like object with the info set.
 */
export declare const overwriteInfo: <T extends SegmentInfo, S extends ISegmentPrivate = ISegmentPrivate>(segmentLike: S, info: T) => SegmentWithInfo<T, S>;
//# sourceMappingURL=segmentInfos.d.ts.map