/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { type AnchorNode, type ExclusiveMapTree, type FieldKey, type FieldUpPath, type MapTree, type TreeFieldStoredSchema, type TreeNodeSchemaIdentifier, type TreeStoredSchema, type Value } from "../../core/index.js";
import { type FlexTreeContext, FlexTreeEntityKind, type FlexTreeField, type FlexTreeNode, type FlexTreeSequenceField, type FlexTreeTypedField, flexTreeMarker, type FlexTreeHydratedContext } from "../flex-tree/index.js";
import { FlexFieldSchema, type FlexTreeNodeSchema, type FlexTreeSchema } from "../typed-schema/index.js";
import type { FlexFieldKind } from "../modular-schema/index.js";
import { type SequenceFieldEditBuilder } from "../default-schema/index.js";
/**
 * A readonly {@link FlexTreeNode} which wraps a {@link MapTree}.
 * @remarks Reading data from the MapTreeNode will read the corresponding data from the {@link MapTree}.
 * Create a `MapTreeNode` by calling {@link getOrCreateMapTreeNode}.
 */
export interface MapTreeNode extends FlexTreeNode {
    readonly mapTree: MapTree;
}
/**
 * Checks if the given {@link FlexTreeNode} is a {@link MapTreeNode}.
 */
export declare function isMapTreeNode(flexNode: FlexTreeNode): flexNode is MapTreeNode;
/**
 * Checks if the given {@link FlexTreeField} is a {@link MapTreeSequenceField}.
 */
export declare function isMapTreeSequenceField(field: FlexTreeSequenceField | FlexTreeField): field is MapTreeSequenceField;
/**
 * An unhydrated {@link FlexTreeSequenceField}, which has additional editing capabilities.
 * @remarks When doing a removal edit, a {@link MapTreeSequenceField}'s `editor` returns ownership of the removed {@link ExclusiveMapTree}s to the caller.
 */
export interface MapTreeSequenceField extends FlexTreeSequenceField {
    readonly editor: MapTreeSequenceFieldEditBuilder;
}
interface MapTreeSequenceFieldEditBuilder extends SequenceFieldEditBuilder<ExclusiveMapTree[]> {
    /**
     * Issues a change which removes `count` elements starting at the given `index`.
     * @param index - The index of the first removed element.
     * @param count - The number of elements to remove.
     * @returns the MapTrees that were removed
     */
    remove(index: number, count: number): ExclusiveMapTree[];
}
/** A node's parent field and its index in that field */
interface LocationInField {
    readonly parent: MapTreeField;
    readonly index: number;
}
/**
 * A readonly implementation of {@link FlexTreeNode} which wraps a {@link MapTree}.
 * @remarks Any methods that would mutate the node will fail,
 * as will the querying of data specific to the {@link LazyTreeNode} implementation (e.g. {@link FlexTreeNode.context}).
 * MapTreeNodes are unconditionally cached -
 * when retrieved via {@link getOrCreateNode}, the same {@link MapTree} object will always produce the same `MapTreeNode` object.
 */
export declare class EagerMapTreeNode implements MapTreeNode {
    readonly context: UnhydratedContext;
    readonly flexSchema: FlexTreeNodeSchema;
    /** The underlying {@link MapTree} that this `MapTreeNode` reads its data from */
    readonly mapTree: ExclusiveMapTree;
    private location;
    get schema(): TreeNodeSchemaIdentifier;
    readonly [flexTreeMarker]: FlexTreeEntityKind.Node;
    /**
     * Create a new MapTreeNode.
     * @param location - the parentage of this node, if it is being created underneath an existing node and field, or undefined if not
     * @remarks This class (and its subclasses) should not be directly constructed outside of this module.
     * Instead, use {@link getOrCreateNode} to create a MapTreeNode from a {@link MapTree}.
     * A `MapTreeNode` may never be constructed more than once for the same {@link MapTree} object.
     * Instead, it should always be acquired via {@link getOrCreateNode}.
     */
    constructor(context: UnhydratedContext, flexSchema: FlexTreeNodeSchema, 
    /** The underlying {@link MapTree} that this `MapTreeNode` reads its data from */
    mapTree: ExclusiveMapTree, location?: LocationInField);
    get type(): TreeNodeSchemaIdentifier;
    /**
     * Set this node's parentage (see {@link FlexTreeNode.parentField}).
     * @remarks The node may be given a parent if it has none, or may have its parent removed (by passing `undefined`).
     * However, a node with a parent may not be directly re-assigned a different parent.
     * That likely indicates either an attempted multi-parenting or an attempt to "move" the node, neither of which are supported.
     * Removing a node's parent twice in a row is also not supported, as it likely indicates a bug.
     */
    adoptBy(parent: undefined): void;
    adoptBy(parent: MapTreeField, index: number): void;
    /**
     * The field this tree is in, and the index within that field.
     * @remarks If this node is unparented, this method will return the special {@link unparentedLocation} as the parent.
     */
    get parentField(): LocationInField;
    is(schema: FlexTreeNodeSchema): boolean;
    tryGetField(key: FieldKey): EagerMapTreeField | undefined;
    getBoxed(key: string): FlexTreeField;
    boxedIterator(): IterableIterator<FlexTreeField>;
    keys(): IterableIterator<FieldKey>;
    get value(): Value;
    get anchorNode(): AnchorNode;
    private walkTree;
}
/**
 * Implementation of `FlexTreeContext`.
 *
 * @remarks An editor is required to edit the FlexTree.
 */
export declare class UnhydratedContext implements FlexTreeContext {
    readonly flexSchema: FlexTreeSchema;
    readonly schema: TreeStoredSchema;
    /**
     * @param flexSchema - Schema to use when working with the tree.
     */
    constructor(flexSchema: FlexTreeSchema);
    isHydrated(): this is FlexTreeHydratedContext;
}
/**
 * A readonly {@link FlexTreeField} which wraps an array of {@link MapTrees}.
 * @remarks Reading data from the MapTreeField will read the corresponding data from the {@link MapTree}s.
 * Create a `MapTreeField` by calling {@link getOrCreateField}.
 */
interface MapTreeField extends FlexTreeField {
    readonly mapTrees: readonly MapTree[];
}
declare class EagerMapTreeField implements MapTreeField {
    readonly context: UnhydratedContext;
    readonly flexSchema: FlexFieldSchema;
    readonly key: FieldKey;
    readonly parent: EagerMapTreeNode;
    [flexTreeMarker]: FlexTreeEntityKind.Field;
    get schema(): TreeFieldStoredSchema;
    constructor(context: UnhydratedContext, flexSchema: FlexFieldSchema, key: FieldKey, parent: EagerMapTreeNode);
    get mapTrees(): readonly ExclusiveMapTree[];
    get length(): number;
    is<TKind2 extends FlexFieldKind>(kind: TKind2): this is FlexTreeTypedField<TKind2>;
    boxedIterator(): IterableIterator<FlexTreeNode>;
    boxedAt(index: number): FlexTreeNode | undefined;
    /**
     * Mutate this field.
     * @param edit - A function which receives the current `MapTree`s that comprise the contents of the field so that it may be mutated.
     * The function may mutate the array in place or return a new array.
     * If a new array is returned then it will be used as the new contents of the field, otherwise the original array will be continue to be used.
     * @remarks All edits to the field (i.e. mutations of the field's MapTrees) should be directed through this function.
     * This function ensures that the parent MapTree has no empty fields (which is an invariant of `MapTree`) after the mutation.
     */
    protected edit(edit: (mapTrees: ExclusiveMapTree[]) => void | ExclusiveMapTree[]): void;
    getFieldPath(): FieldUpPath;
}
/**
 * If there exists a {@link EagerMapTreeNode} for the given {@link MapTree}, returns it, otherwise returns `undefined`.
 * @remarks {@link EagerMapTreeNode | MapTreeNodes} are created via {@link getOrCreateNode}.
 */
export declare function tryGetMapTreeNode(mapTree: MapTree): MapTreeNode | undefined;
/**
 * Create a {@link EagerMapTreeNode} that wraps the given {@link MapTree}, or get the node that already exists for that {@link MapTree} if there is one.
 * @param nodeSchema - the {@link FlexTreeNodeSchema | schema} that the node conforms to
 * @param mapTree - the {@link MapTree} containing the data for this node.
 * @remarks It must conform to the `nodeSchema`.
 */
export declare function getOrCreateMapTreeNode(context: UnhydratedContext, nodeSchema: FlexTreeNodeSchema, mapTree: ExclusiveMapTree): EagerMapTreeNode;
export declare function unsupportedUsageError(message?: string): Error;
export {};
//# sourceMappingURL=mapTreeNode.d.ts.map