/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { type TreeStatus } from "../feature-libraries/index.js";
import { NodeKind, type TreeLeafValue, type TreeNodeSchema, type ImplicitAllowedTypes, type TreeNodeFromImplicitAllowedTypes } from "./schemaTypes.js";
import type { TreeNode } from "./types.js";
/**
 * Provides various functions for analyzing {@link TreeNode}s.
 * * @remarks
 * This type should only be used via the public `Tree` export.
 * @privateRemarks
 * Due to limitations of API-Extractor link resolution, this type can't be moved into internalTypes but should be considered just an implementation detail of the `Tree` export.
 *
 * Inlining the typing of this interface onto the `Tree` object provides slightly different .d.ts generation,
 * which avoids typescript expanding the type of TreeNodeSchema and thus encountering
 * https://github.com/microsoft/rushstack/issues/1958.
 * @sealed @public
 */
export interface TreeNodeApi {
    /**
     * The schema information for this node.
     */
    schema<T extends TreeNode | TreeLeafValue>(node: T): TreeNodeSchema<string, NodeKind, unknown, T>;
    /**
     * Narrow the type of the given value if it satisfies the given schema.
     * @example
     * ```ts
     * if (node.is(myNode, Point)) {
     *     const y = myNode.y; // `myNode` is now known to satisfy the `Point` schema and therefore has a `y` coordinate.
     * }
     * ```
     */
    is<TSchema extends ImplicitAllowedTypes>(value: unknown, schema: TSchema): value is TreeNodeFromImplicitAllowedTypes<TSchema>;
    /**
     * Return the node under which this node resides in the tree (or undefined if this is a root node of the tree).
     */
    parent(node: TreeNode): TreeNode | undefined;
    /**
     * The key of the given node under its parent.
     * @remarks
     * If `node` is an element in a {@link (TreeArrayNode:interface)}, this returns the index of `node` in the array node (a `number`).
     * Otherwise, this returns the key of the field that it is under (a `string`).
     */
    key(node: TreeNode): string | number;
    /**
     * Register an event listener on the given node.
     * @param node - The node whose events should be subscribed to.
     * @param eventName - Which event to subscribe to.
     * @param listener - The callback to trigger for the event. The tree can be read during the callback, but it is invalid to modify the tree during this callback.
     * @returns A callback function which will deregister the event.
     * This callback should be called only once.
     */
    on<K extends keyof TreeChangeEvents>(node: TreeNode, eventName: K, listener: TreeChangeEvents[K]): () => void;
    /**
     * Returns the {@link TreeStatus} of the given node.
     */
    readonly status: (node: TreeNode) => TreeStatus;
    /**
     * Returns the {@link SchemaFactory.identifier | identifier} of the given node in the most compressed form possible.
     * @remarks
     * If the node's identifier is a valid UUID that was automatically generated by the SharedTree, then this will return a process-unique integer corresponding to that identifier.
     * This is useful for performance-sensitive scenarios involving many nodes with identifiers that need to be compactly retained in memory or used for efficient lookup.
     *
     * If the node's identifier is any other user-provided string, then this will return that string.
     *
     * If the node has no identifier (that is, it has no {@link SchemaFactory.identifier | identifier} field), then this returns `undefined`.
     *
     * If the node has more than one identifier, then this will throw an error.
     *
     * The returned integer must not be serialized or preserved outside of the current process.
     * Its lifetime is that of the current in-memory instance of the FF container for this client, and it is not guaranteed to be unique or stable outside of that context.
     * The same node's identifier may, for example, be different across multiple sessions for the same client and document, or different across two clients in the same session.
     */
    shortId(node: TreeNode): number | string | undefined;
}
/**
 * The `Tree` object holds various functions for analyzing {@link TreeNode}s.
 */
export declare const treeNodeApi: TreeNodeApi;
/**
 * Returns a schema for a value if the value is a {@link TreeNode} or a {@link TreeLeafValue}.
 * Returns undefined for other values.
 */
export declare function tryGetSchema<T>(value: T): undefined | TreeNodeSchema<string, NodeKind, unknown, T>;
/**
 * A collection of events that can be emitted by a {@link TreeNode}.
 *
 * @privateRemarks
 * TODO: add a way to subscribe to a specific field (for nodeChanged and treeChanged).
 * Probably have object node and map node specific APIs for this.
 *
 * TODO: ensure that subscription API for fields aligns with API for subscribing to the root.
 *
 * TODO: add more wider area (avoid needing tons of nodeChanged registration) events for use-cases other than treeChanged.
 * Some ideas:
 *
 * - treeChanged, but with some subtrees/fields/paths excluded
 * - helper to batch several nodeChanged calls to a treeChanged scope
 * - parent change (ex: registration on the parent field for a specific index: maybe allow it for a range. Ex: node event takes optional field and optional index range?)
 * - new content inserted into subtree. Either provide event for this and/or enough info to treeChanged to find and search the new sub-trees.
 * Add separate (non event related) API to efficiently scan tree for given set of types (using low level cursor and schema based filtering)
 * to allow efficiently searching for new content (and initial content) of a given type.
 *
 * @sealed @public
 */
export interface TreeChangeEvents {
    /**
     * Emitted by a node after a batch of changes has been applied to the tree, if a change affected the node, where a
     * change is:
     *
     * - For an object node, when the value of one of its properties changes (i.e., the property's value is set
     * to something else, including `undefined`).
     *
     * - For an array node, when an element is added, removed, or moved.
     *
     * - For a map node, when an entry is added, updated, or removed.
     *
     * @remarks
     * This event is not emitted when:
     *
     * - Properties of a child node change. Notably, updates to an array node or a map node (like adding or removing
     * elements/entries) will emit this event on the array/map node itself, but not on the node that contains the
     * array/map node as one of its properties.
     *
     * - The node is moved to a different location in the tree or removed from the tree.
     * In this case the event is emitted on the _parent_ node, not the node itself.
     *
     * For remote edits, this event is not guaranteed to occur in the same order or quantity that it did in
     * the client that made the original edit.
     *
     * When it is emitted, the tree is guaranteed to be in-schema.
     *
     * @privateRemarks
     * This event occurs whenever the apparent contents of the node instance change, regardless of what caused the change.
     * For example, it will fire when the local client reassigns a child, when part of a remote edit is applied to the
     * node, or when the node has to be updated due to resolution of a merge conflict
     * (for example a previously applied local change might be undone, then reapplied differently or not at all).
     */
    nodeChanged(): void;
    /**
     * Emitted by a node after a batch of changes has been applied to the tree, when something changed anywhere in the
     * subtree rooted at it.
     *
     * @remarks
     * This event is not emitted when the node itself is moved to a different location in the tree or removed from the tree.
     * In that case it is emitted on the _parent_ node, not the node itself.
     *
     * The node itself is part of the subtree, so this event will be emitted even if the only changes are to the properties
     * of the node itself.
     *
     * For remote edits, this event is not guaranteed to occur in the same order or quantity that it did in
     * the client that made the original edit.
     *
     * When it is emitted, the tree is guaranteed to be in-schema.
     */
    treeChanged(): void;
}
//# sourceMappingURL=treeNodeApi.d.ts.map