/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { type WithType, NodeKind, type TreeNode, type ImplicitAllowedTypes, type ImplicitAnnotatedAllowedTypes, type InsertableTreeNodeFromImplicitAllowedTypes, type NodeSchemaMetadata, type TreeLeafValue, type TreeNodeFromImplicitAllowedTypes, type TreeNodeSchemaCorePrivate } from "../../core/index.js";
import type { System_Unsafe } from "../../api/index.js";
import type { ArrayNodeCustomizableSchema, ArrayNodePojoEmulationSchema } from "./arrayNodeTypes.js";
import { type JsonCompatibleReadOnlyObject } from "../../../util/index.js";
/**
 * A covariant base type for {@link (TreeArrayNode:interface)}.
 *
 * This provides the readonly subset of TreeArrayNode functionality, and is used as the source interface for moves since that needs to be covariant.
 * @privateRemarks
 * Ideally this would just include `TreeNode, WithType<string, NodeKind.Array>` in the extends list but https://github.com/microsoft/TypeScript/issues/16936 prevents that from compiling.
 * As a workaround around for this TypeScript limitation, the conflicting type intersection is wrapped in `Awaited` (which has no effect on the type in this case) which allows it to compile.
 * @system @sealed @public
 */
export interface ReadonlyArrayNode<out T = TreeNode | TreeLeafValue> extends ReadonlyArray<T>, Awaited<TreeNode & WithType<string, NodeKind.Array>> {
}
/**
 * A {@link TreeNode} which implements 'readonly T[]' and the array mutation APIs.
 *
 * @typeParam TAllowedTypes - Schema for types which are allowed as members of this array.
 * @typeParam T - Use Default: Do not specify. Type of values to read from the array.
 * @typeParam TNew - Use Default: Do not specify. Type of values to write into the array.
 * @typeParam TMoveFrom - Use Default: Do not specify. Type of node from which children can be moved into this array.
 *
 * @sealed @public
 */
export interface TreeArrayNode<TAllowedTypes extends System_Unsafe.ImplicitAllowedTypesUnsafe = ImplicitAllowedTypes, out T = [TAllowedTypes] extends [ImplicitAllowedTypes] ? TreeNodeFromImplicitAllowedTypes<TAllowedTypes> : TreeNodeFromImplicitAllowedTypes<ImplicitAllowedTypes>, in TNew = [TAllowedTypes] extends [ImplicitAllowedTypes] ? InsertableTreeNodeFromImplicitAllowedTypes<TAllowedTypes> : InsertableTreeNodeFromImplicitAllowedTypes<ImplicitAllowedTypes>, in TMoveFrom = ReadonlyArrayNode> extends ReadonlyArrayNode<T> {
    /**
     * Inserts new item(s) at a specified location.
     * @param index - The index at which to insert `value`.
     * @param value - The content to insert.
     * @throws Throws if `index` is not in the range [0, `array.length`).
     */
    insertAt(index: number, ...value: readonly (TNew | IterableTreeArrayContent<TNew>)[]): void;
    /**
     * Inserts new item(s) at the start of the array.
     * @param value - The content to insert.
     */
    insertAtStart(...value: readonly (TNew | IterableTreeArrayContent<TNew>)[]): void;
    /**
     * Inserts new item(s) at the end of the array.
     * @param value - The content to insert.
     */
    insertAtEnd(...value: readonly (TNew | IterableTreeArrayContent<TNew>)[]): void;
    /**
     * Removes the item at the specified location.
     * @param index - The index at which to remove the item.
     * @throws Throws if `index` is not in the range [0, `array.length`).
     */
    removeAt(index: number): void;
    /**
     * Removes all items between the specified indices.
     * @param start - The starting index of the range to remove (inclusive). Defaults to the start of the array.
     * @param end - The ending index of the range to remove (exclusive). Defaults to `array.length`.
     * @throws Throws if `start` is not in the range [0, `array.length`].
     * @throws Throws if `end` is less than `start`.
     * If `end` is not supplied or is greater than the length of the array, all items after `start` are removed.
     *
     * @remarks
     * The default values for start and end are computed when this is called,
     * and thus the behavior is the same as providing them explicitly, even with respect to merge resolution with concurrent edits.
     * For example, two concurrent transactions both emptying the array with `node.removeRange()` then inserting an item,
     * will merge to result in the array having both inserted items.
     */
    removeRange(start?: number, end?: number): void;
    /**
     * Moves the specified item to the start of the array.
     * @param sourceIndex - The index of the item to move.
     * @throws Throws if `sourceIndex` is not in the range [0, `array.length`).
     */
    moveToStart(sourceIndex: number): void;
    /**
     * Moves the specified item to the start of the array.
     * @param sourceIndex - The index of the item to move.
     * @param source - The source array to move the item out of.
     * @throws Throws if `sourceIndex` is not in the range [0, `array.length`).
     */
    moveToStart(sourceIndex: number, source: TMoveFrom): void;
    /**
     * Moves the specified item to the end of the array.
     * @param sourceIndex - The index of the item to move.
     * @throws Throws if `sourceIndex` is not in the range [0, `array.length`).
     */
    moveToEnd(sourceIndex: number): void;
    /**
     * Moves the specified item to the end of the array.
     * @param sourceIndex - The index of the item to move.
     * @param source - The source array to move the item out of.
     * @throws Throws if `sourceIndex` is not in the range [0, `array.length`).
     */
    moveToEnd(sourceIndex: number, source: TMoveFrom): void;
    /**
     * Moves the specified item to the desired location in the array.
     *
     * WARNING - This API is easily misused.
     * Please read the documentation for the `destinationGap` parameter carefully.
     *
     * @param destinationGap - The location *between* existing items that the moved item should be moved to.
     *
     * WARNING - `destinationGap` describes a location between existing items *prior to applying the move operation*.
     *
     * For example, if the array contains items `[A, B, C]` before the move, the `destinationGap` must be one of the following:
     *
     * - `0` (between the start of the array and `A`'s original position)
     *
     * - `1` (between `A`'s original position and `B`'s original position)
     *
     * - `2` (between `B`'s original position and `C`'s original position)
     *
     * - `3` (between `C`'s original position and the end of the array)
     *
     * So moving `A` between `B` and `C` would require `destinationGap` to be `2`.
     *
     * This interpretation of `destinationGap` makes it easy to specify the desired destination relative to a sibling item that is not being moved,
     * or relative to the start or end of the array:
     *
     * - Move to the start of the array: `array.moveToIndex(0, ...)` (see also `moveToStart`)
     *
     * - Move to before some item X: `array.moveToIndex(indexOfX, ...)`
     *
     * - Move to after some item X: `array.moveToIndex(indexOfX + 1`, ...)
     *
     * - Move to the end of the array: `array.moveToIndex(array.length, ...)` (see also `moveToEnd`)
     *
     * This interpretation of `destinationGap` does however make it less obvious how to move an item relative to its current position:
     *
     * - Move item B before its predecessor: `array.moveToIndex(indexOfB - 1, ...)`
     *
     * - Move item B after its successor: `array.moveToIndex(indexOfB + 2, ...)`
     *
     * Notice the asymmetry between `-1` and `+2` in the above examples.
     * In such scenarios, it can often be easier to approach such edits by swapping adjacent items:
     * If items A and B are adjacent, such that A precedes B,
     * then they can be swapped with `array.moveToIndex(indexOfA, indexOfB)`.
     *
     * @param sourceIndex - The index of the item to move.
     * @throws Throws if any of the input indices are not in the range [0, `array.length`).
     */
    moveToIndex(destinationGap: number, sourceIndex: number): void;
    /**
     * Moves the specified item to the desired location in the array.
     *
     * WARNING - This API is easily misused.
     * Please read the documentation for the `destinationGap` parameter carefully.
     *
     * @param destinationGap - The location *between* existing items that the moved item should be moved to.
     *
     * WARNING - `destinationGap` describes a location between existing items *prior to applying the move operation*.
     *
     * For example, if the array contains items `[A, B, C]` before the move, the `destinationGap` must be one of the following:
     *
     * - `0` (between the start of the array and `A`'s original position)
     *
     * - `1` (between `A`'s original position and `B`'s original position)
     *
     * - `2` (between `B`'s original position and `C`'s original position)
     *
     * - `3` (between `C`'s original position and the end of the array)
     *
     * So moving `A` between `B` and `C` would require `destinationGap` to be `2`.
     *
     * This interpretation of `destinationGap` makes it easy to specify the desired destination relative to a sibling item that is not being moved,
     * or relative to the start or end of the array:
     *
     * - Move to the start of the array: `array.moveToIndex(0, ...)` (see also `moveToStart`)
     *
     * - Move to before some item X: `array.moveToIndex(indexOfX, ...)`
     *
     * - Move to after some item X: `array.moveToIndex(indexOfX + 1`, ...)
     *
     * - Move to the end of the array: `array.moveToIndex(array.length, ...)` (see also `moveToEnd`)
     *
     * This interpretation of `destinationGap` does however make it less obvious how to move an item relative to its current position:
     *
     * - Move item B before its predecessor: `array.moveToIndex(indexOfB - 1, ...)`
     *
     * - Move item B after its successor: `array.moveToIndex(indexOfB + 2, ...)`
     *
     * Notice the asymmetry between `-1` and `+2` in the above examples.
     * In such scenarios, it can often be easier to approach such edits by swapping adjacent items:
     * If items A and B are adjacent, such that A precedes B,
     * then they can be swapped with `array.moveToIndex(indexOfA, indexOfB)`.
     *
     * @param sourceIndex - The index of the item to move.
     * @param source - The source array to move the item out of.
     * @throws Throws if any of the source index is not in the range [0, `array.length`),
     * or if the index is not in the range [0, `array.length`].
     */
    moveToIndex(destinationGap: number, sourceIndex: number, source: TMoveFrom): void;
    /**
     * Moves the specified items to the start of the array.
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @throws Throws if either of the input indices are not in the range [0, `array.length`) or if `sourceStart` is greater than `sourceEnd`.
     * if any of the input indices are not in the range [0, `array.length`], or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToStart(sourceStart: number, sourceEnd: number): void;
    /**
     * Moves the specified items to the start of the array.
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @param source - The source array to move items out of.
     * @throws Throws if the types of any of the items being moved are not allowed in the destination array,
     * if either of the input indices are not in the range [0, `array.length`) or if `sourceStart` is greater than `sourceEnd`.
     * if any of the input indices are not in the range [0, `array.length`], or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToStart(sourceStart: number, sourceEnd: number, source: TMoveFrom): void;
    /**
     * Moves the specified items to the end of the array.
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @throws Throws if either of the input indices are not in the range [0, `array.length`) or if `sourceStart` is greater than `sourceEnd`.
     * if any of the input indices are not in the range [0, `array.length`], or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToEnd(sourceStart: number, sourceEnd: number): void;
    /**
     * Moves the specified items to the end of the array.
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @param source - The source array to move items out of.
     * @throws Throws if the types of any of the items being moved are not allowed in the destination array,
     * if either of the input indices are not in the range [0, `array.length`) or if `sourceStart` is greater than `sourceEnd`.
     * if any of the input indices are not in the range [0, `array.length`], or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToEnd(sourceStart: number, sourceEnd: number, source: TMoveFrom): void;
    /**
     * Moves the specified items to the desired location within the array.
     *
     * WARNING - This API is easily misused.
     * Please read the documentation for the `destinationGap` parameter carefully.
     *
     * @param destinationGap - The location *between* existing items that the moved item should be moved to.
     *
     * WARNING - `destinationGap` describes a location between existing items *prior to applying the move operation*.
     *
     * For example, if the array contains items `[A, B, C]` before the move, the `destinationGap` must be one of the following:
     *
     * - `0` (between the start of the array and `A`'s original position)
     *
     * - `1` (between `A`'s original position and `B`'s original position)
     *
     * - `2` (between `B`'s original position and `C`'s original position)
     *
     * - `3` (between `C`'s original position and the end of the array)
     *
     * So moving `A` between `B` and `C` would require `destinationGap` to be `2`.
     *
     * This interpretation of `destinationGap` makes it easy to specify the desired destination relative to a sibling item that is not being moved,
     * or relative to the start or end of the array:
     *
     * - Move to the start of the array: `array.moveToIndex(0, ...)` (see also `moveToStart`)
     *
     * - Move to before some item X: `array.moveToIndex(indexOfX, ...)`
     *
     * - Move to after some item X: `array.moveToIndex(indexOfX + 1`, ...)
     *
     * - Move to the end of the array: `array.moveToIndex(array.length, ...)` (see also `moveToEnd`)
     *
     * This interpretation of `destinationGap` does however make it less obvious how to move an item relative to its current position:
     *
     * - Move item B before its predecessor: `array.moveToIndex(indexOfB - 1, ...)`
     *
     * - Move item B after its successor: `array.moveToIndex(indexOfB + 2, ...)`
     *
     * Notice the asymmetry between `-1` and `+2` in the above examples.
     * In such scenarios, it can often be easier to approach such edits by swapping adjacent items:
     * If items A and B are adjacent, such that A precedes B,
     * then they can be swapped with `array.moveToIndex(indexOfA, indexOfB)`.
     *
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @throws Throws if any of the input indices are not in the range [0, `array.length`) or if `sourceStart` is greater than `sourceEnd`.
     * if any of the input indices are not in the range [0, `array.length`], or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToIndex(destinationGap: number, sourceStart: number, sourceEnd: number): void;
    /**
     * Moves the specified items to the desired location within the array.
     *
     * WARNING - This API is easily misused.
     * Please read the documentation for the `destinationGap` parameter carefully.
     *
     * @param destinationGap - The location *between* existing items that the moved item should be moved to.
     *
     * WARNING - `destinationGap` describes a location between existing items *prior to applying the move operation*.
     *
     * For example, if the array contains items `[A, B, C]` before the move, the `destinationGap` must be one of the following:
     *
     * - `0` (between the start of the array and `A`'s original position)
     *
     * - `1` (between `A`'s original position and `B`'s original position)
     *
     * - `2` (between `B`'s original position and `C`'s original position)
     *
     * - `3` (between `C`'s original position and the end of the array)
     *
     * So moving `A` between `B` and `C` would require `destinationGap` to be `2`.
     *
     * This interpretation of `destinationGap` makes it easy to specify the desired destination relative to a sibling item that is not being moved,
     * or relative to the start or end of the array:
     *
     * - Move to the start of the array: `array.moveToIndex(0, ...)` (see also `moveToStart`)
     *
     * - Move to before some item X: `array.moveToIndex(indexOfX, ...)`
     *
     * - Move to after some item X: `array.moveToIndex(indexOfX + 1`, ...)
     *
     * - Move to the end of the array: `array.moveToIndex(array.length, ...)` (see also `moveToEnd`)
     *
     * This interpretation of `destinationGap` does however make it less obvious how to move an item relative to its current position:
     *
     * - Move item B before its predecessor: `array.moveToIndex(indexOfB - 1, ...)`
     *
     * - Move item B after its successor: `array.moveToIndex(indexOfB + 2, ...)`
     *
     * Notice the asymmetry between `-1` and `+2` in the above examples.
     * In such scenarios, it can often be easier to approach such edits by swapping adjacent items:
     * If items A and B are adjacent, such that A precedes B,
     * then they can be swapped with `array.moveToIndex(indexOfA, indexOfB)`.
     *
     * @param sourceStart - The starting index of the range to move (inclusive).
     * @param sourceEnd - The ending index of the range to move (exclusive)
     * @param source - The source array to move items out of.
     * @throws Throws if the types of any of the items being moved are not allowed in the destination array,
     * if any of the input indices are not in the range [0, `array.length`], or if `sourceStart` is greater than `sourceEnd`.
     */
    moveRangeToIndex(destinationGap: number, sourceStart: number, sourceEnd: number, source: TMoveFrom): void;
    /**
     * Returns a custom IterableIterator which throws usage errors if concurrent editing and iteration occurs.
     */
    values(): IterableIterator<T>;
}
/**
 * A {@link TreeNode} which implements 'readonly T[]' and the array mutation APIs.
 * @public
 */
export declare const TreeArrayNode: {
    /**
     * Wrap an iterable of items to inserted as consecutive items in a array.
     * @remarks
     * The object returned by this function can be inserted into a {@link (TreeArrayNode:interface)}.
     * Its contents will be inserted consecutively in the corresponding location in the array.
     * @example
     * ```ts
     * array.insertAtEnd(TreeArrayNode.spread(iterable))
     * ```
     */
    readonly spread: <T>(content: Iterable<T>) => IterableTreeArrayContent<T>;
};
/**
 * Used to insert iterable content into a {@link (TreeArrayNode:interface)}.
 * Use {@link (TreeArrayNode:variable).spread} to create an instance of this type.
 * @sealed @public
 */
export declare class IterableTreeArrayContent<T> implements Iterable<T> {
    private readonly content;
    private constructor();
    /**
     * Iterates over content for nodes to insert.
     */
    [Symbol.iterator](): Iterator<T>;
}
/**
 * Attempts to coerce the given property key to an integer index property.
 * @param key - The property key to coerce.
 * @param exclusiveMax - This restricts the range in which the resulting index is allowed to be.
 * The coerced index of `key` must be less than `exclusiveMax` or else this function will return `undefined`.
 * This is useful for reading an array within the bounds of its length, e.g. `asIndex(key, array.length)`.
 */
export declare function asIndex(key: string | symbol, exclusiveMax: number): number | undefined;
/**
 * Define a {@link TreeNodeSchema} for a {@link (TreeArrayNode:interface)}.
 *
 * @param name - Unique identifier for this schema including the factory's scope.
 * @param persistedMetadata - Optional persisted metadata for the object node schema.
 */
export declare function arraySchema<TName extends string, const T extends ImplicitAnnotatedAllowedTypes, const ImplicitlyConstructable extends boolean, const TCustomMetadata = unknown>(identifier: TName, info: T, implicitlyConstructable: ImplicitlyConstructable, customizable: boolean, metadata?: NodeSchemaMetadata<TCustomMetadata>, persistedMetadata?: JsonCompatibleReadOnlyObject | undefined): ArrayNodeCustomizableSchema<TName, T, ImplicitlyConstructable, TCustomMetadata> & ArrayNodePojoEmulationSchema<TName, T, ImplicitlyConstructable, TCustomMetadata> & TreeNodeSchemaCorePrivate<string, NodeKind, never, boolean, unknown, unknown>;
//# sourceMappingURL=arrayNode.d.ts.map