import { EmptyBase, NonEmptyBase } from '@rimbu/collection-types/map-custom';
import { IndexRange, OptLazy, TraverseState } from '@rimbu/common';
import { Stream } from '@rimbu/stream';
/**
 * Base implementation used for empty sorted collections.<br/>
 * <br/>
 * Provides the index‑based operations used by `SortedMap` / `SortedSet`
 * instances when they are empty and always returns the given fallback value.
 */
export declare class SortedEmpty extends EmptyBase {
    min<O>(otherwise?: OptLazy<O>): O;
    max<O>(otherwise?: OptLazy<O>): O;
    getAtIndex<O>(index: number, otherwise?: OptLazy<O>): O;
    take(): any;
    drop(): any;
    sliceIndex(): any;
}
/**
 * Abstract base class for non‑empty sorted collections.<br/>
 * <br/>
 * It exposes the common index‑based operations and structural mutation
 * helpers shared by the sorted map and set node implementations.
 * @typeparam E - the stored entry type
 * @typeparam TS - the concrete non‑empty node type
 */
export declare abstract class SortedNonEmptyBase<E, TS extends SortedNonEmptyBase<E, TS>> extends NonEmptyBase<E> {
    abstract getAtIndex<O>(index: number, otherwise?: OptLazy<O>): E | O;
    abstract get entries(): readonly E[];
    abstract takeInternal(amount: number): TS;
    abstract dropInternal(amount: number): TS;
    abstract mutateSplitRight(index?: number): [E, TS];
    abstract mutateGiveToLeft(left: TS, toLeft: E): [E, TS];
    abstract mutateGiveToRight(right: TS, toRight: E): [E, TS];
    abstract mutateGetFromLeft(left: TS, toMe: E): [E, TS];
    abstract mutateGetFromRight(right: TS, toMe: E): [E, TS];
    abstract mutateJoinLeft(left: TS, entry: E): void;
    abstract mutateJoinRight(right: TS, entry: E): void;
    abstract deleteMin(): [E, TS];
    abstract deleteMax(): [E, TS];
    get mutateEntries(): E[];
}
/**
 * Describes the mutable surface of a leaf node used by the helper
 * functions that transform B‑tree leaves.
 * @typeparam TS - the concrete leaf type
 * @typeparam E - the stored entry type
 */
export interface LeafMutateSource<TS extends LeafMutateSource<TS, E>, E> {
    mutateEntries: E[];
    entries: readonly E[];
    copy(entries: readonly E[]): TS;
}
/**
 * Removes and returns the minimum entry from the given leaf node while
 * returning the updated leaf.
 * @param source - the leaf node to operate on
 */
export declare function leafDeleteMin<S extends LeafMutateSource<S, E>, E>(source: S): [E, S];
/**
 * Removes and returns the maximum entry from the given leaf node while
 * returning the updated leaf.
 * @param source - the leaf node to operate on
 */
export declare function leafDeleteMax<S extends LeafMutateSource<S, E>, E>(source: S): [E, S];
/**
 * Splits the given leaf node into two nodes and returns the promoted
 * separator entry together with the newly created right node.<br/>
 * <br/>
 * The split position can be customised through the optional `index`.
 * @param source - the leaf node to split
 * @param index - (optional) the split index, defaults to the middle entry
 */
export declare function leafMutateSplitRight<S extends LeafMutateSource<S, E>, E>(source: S, index?: number): [E, S];
/**
 * Moves the given `toLeft` entry from `source` to the left sibling and
 * returns the separator entry that should be stored in the parent node.
 * @param source - the leaf that donates an entry to the left sibling
 * @param left - the left sibling leaf to receive the entry
 * @param toLeft - the entry that must end up in the left sibling
 */
export declare function leafMutateGiveToLeft<S extends LeafMutateSource<S, E>, E>(source: S, left: S, toLeft: E): [E, S];
/**
 * Moves the given `toRight` entry from `source` to the right sibling and
 * returns the separator entry that should be stored in the parent node.
 * @param source - the leaf that donates an entry to the right sibling
 * @param right - the right sibling leaf to receive the entry
 * @param toRight - the entry that must end up in the right sibling
 */
export declare function leafMutateGiveToRight<S extends LeafMutateSource<S, E>, E>(source: S, right: S, toRight: E): [E, S];
/**
 * Pulls an entry from the left sibling into `source` and returns the
 * separator entry that should be stored in the parent node.
 * @param source - the leaf receiving an entry
 * @param left - the left sibling leaf to donate an entry
 * @param toMe - the entry that must end up in `source`
 */
export declare function leafMutateGetFromLeft<S extends LeafMutateSource<S, E>, E>(source: S, left: S, toMe: E): [E, S];
/**
 * Pulls an entry from the right sibling into `source` and returns the
 * separator entry that should be stored in the parent node.
 * @param source - the leaf receiving an entry
 * @param right - the right sibling leaf to donate an entry
 * @param toMe - the entry that must end up in `source`
 */
export declare function leafMutateGetFromRight<S extends LeafMutateSource<S, E>, E>(source: S, right: S, toMe: E): [E, S];
/**
 * Joins the given left sibling leaf and `source` into a single leaf by
 * inserting the given separator `entry` between them.
 * @param source - the right leaf that will absorb the left sibling
 * @param left - the left sibling leaf to merge
 * @param entry - the separator entry from the parent
 */
export declare function leafMutateJoinLeft<S extends LeafMutateSource<S, E>, E>(source: S, left: S, entry: E): void;
/**
 * Joins the given right sibling leaf and `source` into a single leaf by
 * inserting the given separator `entry` between them.
 * @param source - the left leaf that will absorb the right sibling
 * @param right - the right sibling leaf to merge
 * @param entry - the separator entry from the parent
 */
export declare function leafMutateJoinRight<S extends LeafMutateSource<S, E>, E>(source: S, right: S, entry: E): void;
/**
 * Describes the minimal interface required from an inner B‑tree node
 * used by the helper functions that transform inner nodes.
 * @typeparam E - the stored entry type
 */
export interface InnerChild<E> {
    readonly size: number;
    getAtIndex<O>(index: number, otherwise?: OptLazy<O>): E | O;
    stream(options?: {
        reversed?: boolean;
    }): Stream<E>;
    streamSliceIndex(range: IndexRange, options?: {
        reversed?: boolean;
    }): Stream<E>;
    readonly entries: readonly E[];
    takeInternal(amount: number): InnerChild<E>;
    dropInternal(amount: number): InnerChild<E>;
    deleteMin(): [E, InnerChild<E>];
    deleteMax(): [E, InnerChild<E>];
    mutateGiveToLeft(left: InnerChild<E>, toLeft: E): [E, InnerChild<E>];
    mutateGiveToRight(right: InnerChild<E>, toRight: E): [E, InnerChild<E>];
    mutateSplitRight(index?: number): [E, InnerChild<E>];
    mutateJoinLeft(left: InnerChild<E>, entry: E): void;
    mutateJoinRight(right: InnerChild<E>, entry: E): void;
    mutateGetFromLeft(left: InnerChild<E>, toMe: E): [E, InnerChild<E>];
    mutateGetFromRight(right: InnerChild<E>, toMe: E): [E, InnerChild<E>];
}
/**
 * Describes the mutable surface of an inner node used by the inner
 * transformation helper functions.
 * @typeparam TS - the concrete inner node type
 * @typeparam E - the stored entry type
 */
export interface InnerMutateSource<TS extends InnerMutateSource<TS, E>, E> {
    readonly context: {
        readonly minEntries: number;
        readonly maxEntries: number;
        inner(entries: readonly E[], children: readonly InnerChild<E>[], size: number): TS;
    };
    size: number;
    entries: readonly E[];
    mutateEntries: E[];
    children: readonly InnerChild<E>[];
    mutateChildren: InnerChild<E>[];
    stream(options?: {
        reversed?: boolean;
    }): Stream.NonEmpty<E>;
    copy(entries?: readonly E[], children?: readonly InnerChild<E>[], size?: number): TS;
    addInternal(entry: E): TS;
    normalizeDownsizeChild(childIndex: number, newChild: InnerChild<E>, newSize: number): TS;
    normalizeIncreaseChild(childIndex: number, newChild: InnerChild<E>, newSize: number): TS;
}
/**
 * Removes and returns the minimum entry from the left‑most child of the
 * given inner node and returns the updated node.
 * @param source - the inner node to operate on
 */
export declare function innerDeleteMin<S extends InnerMutateSource<S, E>, E>(source: S): [E, S];
/**
 * Removes and returns the maximum entry from the right‑most child of the
 * given inner node and returns the updated node.
 * @param source - the inner node to operate on
 */
export declare function innerDeleteMax<S extends InnerMutateSource<S, E>, E>(source: S): [E, S];
/**
 * Splits the given inner node into two nodes and returns the promoted
 * separator entry together with the new right node.<br/>
 * <br/>
 * The split position can be customised through the optional `index`.
 * @param source - the inner node to split
 * @param index - (optional) the split index, defaults to the middle entry
 */
export declare function innerMutateSplitRight<S extends InnerMutateSource<S, E>, E>(source: S, index?: number): [E, S];
/**
 * Moves the given `toLeft` entry and its child from `source` to the left
 * sibling and returns the separator entry that should be stored in the
 * parent node.
 * @param source - the inner node donating an entry to the left sibling
 * @param left - the left sibling node to receive the entry and child
 * @param toLeft - the entry that must end up in the left sibling
 */
export declare function innerMutateGiveToLeft<S extends InnerMutateSource<S, E>, E>(source: S, left: S, toLeft: E): [E, S];
/**
 * Moves the given `toRight` entry and its child from `source` to the right
 * sibling and returns the separator entry that should be stored in the
 * parent node.
 * @param source - the inner node donating an entry to the right sibling
 * @param right - the right sibling node to receive the entry and child
 * @param toRight - the entry that must end up in the right sibling
 */
export declare function innerMutateGiveToRight<S extends InnerMutateSource<S, E>, E>(source: S, right: S, toRight: E): [E, S];
/**
 * Pulls an entry and child from the left sibling into `source` and returns
 * the separator entry that should be stored in the parent node.
 * @param source - the inner node receiving the entry and child
 * @param left - the left sibling node to donate the entry and child
 * @param toMe - the entry that must end up in `source`
 */
export declare function innerMutateGetFromLeft<S extends InnerMutateSource<S, E>, E>(source: S, left: S, toMe: E): [E, S];
/**
 * Pulls an entry and child from the right sibling into `source` and returns
 * the separator entry that should be stored in the parent node.
 * @param source - the inner node receiving the entry and child
 * @param right - the right sibling node to donate the entry and child
 * @param toMe - the entry that must end up in `source`
 */
export declare function innerMutateGetFromRight<S extends InnerMutateSource<S, E>, E>(source: S, right: S, toMe: E): [E, S];
/**
 * Joins the given left sibling inner node and `source` into a single node by
 * inserting the given separator `entry` between them.
 * @param source - the right inner node that will absorb the left sibling
 * @param left - the left sibling node to merge
 * @param entry - the separator entry from the parent
 */
export declare function innerMutateJoinLeft<S extends InnerMutateSource<S, E>, E>(source: S, left: S, entry: E): void;
/**
 * Joins the given right sibling inner node and `source` into a single node by
 * inserting the given separator `entry` between them.
 * @param source - the left inner node that will absorb the right sibling
 * @param right - the right sibling node to merge
 * @param entry - the separator entry from the parent
 */
export declare function innerMutateJoinRight<S extends InnerMutateSource<S, E>, E>(source: S, right: S, entry: E): void;
/**
 * Normalises the given child after it has decreased in size so that it
 * satisfies the minimum entry constraint of the B‑tree.<br/>
 * <br/>
 * Depending on the neighbouring children this may rotate entries between
 * nodes or perform a split.
 * @param source - the inner node that contains the child
 * @param childIndex - the index of the child within `source`
 * @param newChild - the updated child node
 * @param newSize - the new total size for `source`
 */
export declare function innerNormalizeDownsizeChild<S extends InnerMutateSource<S, E>, E>(source: S, childIndex: number, newChild: InnerChild<E>, newSize: number): S;
/**
 * Normalises the given child after it has increased in size so that it
 * satisfies the maximum entry constraint of the B‑tree.<br/>
 * <br/>
 * Depending on the neighbouring children this may rotate entries between
 * nodes or merge nodes together.
 * @param source - the inner node that contains the child
 * @param childIndex - the index of the child within `source`
 * @param newChild - the updated child node
 * @param newSize - the new total size for `source`
 */
export declare function innerNormalizeIncreaseChild<S extends InnerMutateSource<S, E>, E>(source: S, childIndex: number, newChild: InnerChild<E>, newSize: number): S;
/**
 * Returns the index of the element in the sources element array, or a tuple with the child index and the index within the child
 * @param source the collection to operate on
 * @param index the index to find
 */
export declare function innerGetSubIndex(source: InnerMutateSource<any, any>, index: number): number | [number, number];
/**
 * Returns the entry at the given `index` from the B‑tree represented by the
 * given inner node, or the provided fallback value if the index is out of
 * bounds.<br/>
 * <br/>
 * Negative indices are interpreted from the end of the collection.
 * @param source - the inner node to read from
 * @param index - the (possibly negative) index to look up
 * @param otherwise - (default: undefined) fallback value when out of bounds
 */
export declare function innerGetAtIndex<E, O>(source: InnerMutateSource<any, E>, index: number, otherwise?: OptLazy<O>): E | O;
/**
 * Returns a new inner node containing only the first `amount` of entries
 * and children of the given `source` node.<br/>
 * <br/>
 * The amount must be between `1` and `source.size - 1`.
 * @param source - the inner node to operate on
 * @param amount - the amount of entries to keep
 */
export declare function innerTakeInternal<S extends InnerMutateSource<S, E>, E>(source: S, amount: number): S;
/**
 * Returns a new inner node containing all entries and children of the given
 * `source` node except for the first `amount` entries.<br/>
 * <br/>
 * The amount must be between `1` and `source.size - 1`.
 * @param source - the inner node to operate on
 * @param amount - the amount of entries to drop
 */
export declare function innerDropInternal<S extends InnerMutateSource<S, E>, E>(source: S, amount: number): S;
/**
 * Returns a `Stream` of entries of the given inner node limited to the
 * provided index `range`.<br/>
 * <br/>
 * When `reversed` is true, the stream iterates the selected range in
 * reverse order.
 * @param source - the inner node to stream from
 * @param range - the index range to include
 * @param reversed - (default: false) when true reverses the stream order
 */
export declare function innerStreamSliceIndex<E>(source: InnerMutateSource<any, E>, range: IndexRange, reversed?: boolean): Stream<E>;
/**
 * Abstract base class for mutable sorted builders used by the sorted map
 * and set implementations.<br/>
 * <br/>
 * It encapsulates the shared tree‑based logic for computing `min`, `max`,
 * index‑based access and traversal while allowing concrete builders to plug
 * in their own entry and child representations.
 * @typeparam E - the entry type stored in the builder
 */
export declare abstract class SortedBuilder<E> {
    abstract get context(): {
        minEntries: number;
        maxEntries: number;
    };
    abstract source?: undefined | {
        min<O>(otherwise?: OptLazy<O>): E | O;
        max<O>(otherwise?: OptLazy<O>): E | O;
        getAtIndex<O>(index: number, otherwise?: OptLazy<O>): E | O;
        forEach(f: (entry: E, index: number, halt: () => void) => void, options?: {
            state?: TraverseState;
        }): void;
    };
    abstract _entries?: undefined | E[];
    abstract _children?: undefined | SortedBuilder<E>[];
    abstract get children(): SortedBuilder<E>[];
    abstract set children(value: SortedBuilder<E>[]);
    abstract size: number;
    abstract prepareMutate(): void;
    abstract createNew(source?: undefined | unknown, entries?: undefined | E[], children?: undefined | SortedBuilder<E>[], size?: undefined | number): SortedBuilder<E>;
    _lock: number;
    /**
     * Throws an error when the builder is mutated while it is being iterated,
     * for example from within {@link SortedBuilder.forEach}.
     */
    checkLock(): void;
    get entries(): E[];
    set entries(value: E[]);
    get hasChildren(): boolean;
    get isEmpty(): boolean;
    /**
     * Returns the minimum entry of the builder, or the given fallback value
     * if the builder is empty.
     * @param otherwise - (default: undefined) fallback value when empty
     */
    min<O>(otherwise?: OptLazy<O>): E | O;
    /**
     * Returns the maximum entry of the builder, or the given fallback value
     * if the builder is empty.
     * @param otherwise - (default: undefined) fallback value when empty
     */
    max<O>(otherwise?: OptLazy<O>): E | O;
    /**
     * Returns the entry at the given `index`, or the provided fallback value
     * when the index is out of bounds.<br/>
     * <br/>
     * Negative indices are interpreted from the end of the builder.
     * @param index - the (possibly negative) index to look up
     * @param otherwise - (default: undefined) fallback value when out of bounds
     */
    getAtIndex<O>(index: number, otherwise?: OptLazy<O>): E | O;
    /**
     * Calls the given function `f` for every entry in the builder in key
     * sort‑order, passing in the entry, its zero‑based index and a `halt`
     * function that can be used to stop iteration early.
     * @param f - the callback function to invoke for each entry
     * @param options - (optional) traversal options including a custom state
     */
    forEach(f: (entry: E, index: number, halt: () => void) => void, options?: {
        state?: TraverseState;
    }): void;
    /**
     * Restores the builder invariants after mutations by splitting the root
     * node when it grows beyond the configured maximum block size.
     */
    normalize(): void;
    normalizeChildIncrease(childIndex: number): void;
    normalizeChildDecrease(childIndex: number): void;
    /**
     * Removes and returns the minimum entry from the builder while keeping
     * the internal B‑tree structure valid.
     */
    deleteMin(): E;
    /**
     * Removes and returns the maximum entry from the builder while keeping
     * the internal B‑tree structure valid.
     */
    deleteMax(): E;
}
