/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { IEditableForest, FieldAnchor, Anchor, Value, ITreeCursor, UpPath, SchemaDataAndPolicy, ForestEvents, FieldUpPath } from "../../core";
import { ISubscribable } from "../../events";
import { DefaultEditBuilder } from "../defaultChangeFamily";
import { ContextuallyTypedFieldData } from "../contextuallyTyped";
import { EditableField, UnwrappedEditableField } from "./editableTreeTypes";
import { ProxyTarget } from "./ProxyTarget";
/**
 * A common context of a "forest" of EditableTrees.
 * It handles group operations like transforming cursors into anchors for edits.
 * @alpha
 */
export interface EditableTreeContext extends ISubscribable<ForestEvents> {
    /**
     * Gets or sets the root field of the tree.
     *
     * When using its setter, the input data must be formed depending
     * on a multiplicity of the field, on if it's polymorphic or not and, for non-sequence multiplicities,
     * on if the field's node declares its primary function by means of a primary field (see `getPrimaryField`):
     * - For `Sequence` multiplicities and "primary fielded" nodes, an array of a {@link ContextuallyTypedNodeData}
     * or an {@link EditableField} is expected.
     * Use an empty array to delete all nodes of a sequence field.
     * - For `Optional` multiplicities, `ContextuallyTypedNodeDataObject | undefined` is expected.
     * If the input data is `undefined`, the field node will be deleted if it exists.
     * - For `Value` multiplicities, `ContextuallyTypedNodeDataObject` is expected.
     *
     * A `PrimitiveValue` can be used instead of a `ContextuallyTypedNodeDataObject`
     * to create/replace or to set the value of the primitive node
     * if the field is a non-sequence and some of its types declare to follow
     * the `String`, `Number` or `Boolean` value schema (see `ValueSchema`).
     * For this to work, it must be possible to resolve the node type by unambiguously matching
     * a basic TypeScript type of the input data to one of the types allowed by the field,
     * or, if the field types are undefined, to one of the types available in the global tree schema.
     * If it's not possible, a `ContextuallyTypedNodeDataObject` with an explicitly provided
     * type and a value (using a `typeNameSymbol` and a `valueSymbol`) must be used instead.
     *
     * Note that currently a setter implementation replaces the nodes and not the field itself,
     * as this is the only option available in the low-level editing API.
     * Replacing the nodes has different merge semantics than replacing the field:
     * it should not overwrite concurrently inserted content while replacing the field should.
     * This might be changed in the future once the low-level editing API is available.
     */
    get root(): EditableField;
    set root(data: ContextuallyTypedFieldData);
    /**
     * Gets or sets the root field of the tree.
     *
     * When using its getter, see {@link UnwrappedEditableField} for what is unwrapped.
     *
     * Currently, its setter works exactly the same way as {@link EditableTreeContext.root},
     * but it might be changed in the future once the low-level editing API
     * for `replaceField` will become available.
     */
    get unwrappedRoot(): UnwrappedEditableField;
    set unwrappedRoot(data: ContextuallyTypedFieldData);
    /**
     * Schema used within this context.
     * All data must conform to these schema.
     *
     * The root's schema is tracked under {@link rootFieldKey}.
     */
    readonly schema: SchemaDataAndPolicy;
    /**
     * Call before editing.
     *
     * Note that after performing edits, EditableTrees for nodes that no longer exist are invalid to use.
     * TODO: maybe add an API to check if a specific EditableTree still exists,
     * and only make use other than that invalid.
     */
    prepareForEdit(): void;
    /**
     * Call to free resources.
     * It is invalid to use the context after this.
     */
    free(): void;
    /**
     * Release any cursors and anchors held by EditableTrees created in this context.
     * The EditableTrees are invalid to use after this, but the context may still be used
     * to create new trees starting from the root.
     */
    clear(): void;
}
/**
 * Implementation of `EditableTreeContext`.
 *
 * An editor is required to edit the EditableTrees.
 */
export declare class ProxyContext implements EditableTreeContext {
    readonly forest: IEditableForest;
    private readonly editor;
    readonly withCursors: Set<ProxyTarget<Anchor | FieldAnchor>>;
    readonly withAnchors: Set<ProxyTarget<Anchor | FieldAnchor>>;
    private readonly eventUnregister;
    /**
     * @param forest - the Forest
     * @param editor - an editor that makes changes to the forest.
     */
    constructor(forest: IEditableForest, editor: DefaultEditBuilder);
    prepareForEdit(): void;
    free(): void;
    clear(): void;
    get unwrappedRoot(): UnwrappedEditableField;
    set unwrappedRoot(value: ContextuallyTypedFieldData);
    get root(): EditableField;
    set root(value: ContextuallyTypedFieldData);
    private getRoot;
    get schema(): SchemaDataAndPolicy;
    setNodeValue(path: UpPath, value: Value): void;
    setValueField(field: FieldUpPath, newContent: ITreeCursor): void;
    setOptionalField(field: FieldUpPath, newContent: ITreeCursor | undefined, wasEmpty: boolean): void;
    insertNodes(field: FieldUpPath, index: number, newContent: ITreeCursor | ITreeCursor[]): void;
    moveNodes(sourceField: FieldUpPath, sourceIndex: number, count: number, destinationField: FieldUpPath, destinationIndex: number): void;
    deleteNodes(field: FieldUpPath, index: number, count: number): void;
    replaceNodes(field: FieldUpPath, index: number, count: number, newContent: ITreeCursor | ITreeCursor[]): void;
    on<K extends keyof ForestEvents>(eventName: K, listener: ForestEvents[K]): () => void;
}
/**
 * A simple API for a Forest to interact with the tree.
 *
 * @param forest - the Forest
 * @param editor - an editor that makes changes to the forest.
 * @returns {@link EditableTreeContext} which is used to manage the cursors and anchors within the EditableTrees:
 * This is necessary for supporting using this tree across edits to the forest, and not leaking memory.
 */
export declare function getEditableTreeContext(forest: IEditableForest, editor: DefaultEditBuilder): EditableTreeContext;
//# sourceMappingURL=editableTreeContext.d.ts.map