/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import type { Listenable } from "@fluidframework/core-interfaces";
import type { TreeNode, Unhydrated } from "./types.js";
import { type AnchorEvents, type AnchorNode, type AnchorSet, type TreeValue, type UpPath } from "../../core/index.js";
import { TreeStatus, type FlexTreeNode } from "../../feature-libraries/index.js";
import type { TreeNodeSchema } from "./treeNodeSchema.js";
import { type Context, type HydratedContext } from "./context.js";
import { UnhydratedFlexTreeNode } from "./unhydratedFlexTree.js";
export declare function getKernel(node: TreeNode): TreeNodeKernel;
/**
 * Detects if the given 'candidate' is a TreeNode.
 *
 * @remarks
 * Supports both Hydrated and {@link Unhydrated} TreeNodes, both of which return true.
 *
 * Because the common usage is to check if a value being inserted/set is a TreeNode,
 * this function permits calling with primitives as well as objects.
 *
 * Primitives will always return false (as they are copies of data, not references to nodes).
 *
 * @param candidate - Value which may be a TreeNode
 * @returns true if the given 'candidate' is a hydrated TreeNode.
 */
export declare function isTreeNode(candidate: unknown): candidate is TreeNode | Unhydrated<TreeNode>;
/**
 * Returns a schema for a value if the value is a {@link TreeNode}.
 *
 * Returns undefined for other values.
 * @remarks
 * Does not give schema for a {@link TreeLeafValue}.
 */
export declare function tryGetTreeNodeSchema(value: unknown): undefined | TreeNodeSchema;
/**
 * Contains state and an internal API for managing {@link TreeNode}s.
 * @remarks All {@link TreeNode}s have an associated kernel object.
 * The kernel has the same lifetime as the node and spans both its unhydrated and hydrated states.
 */
export declare class TreeNodeKernel {
    #private;
    readonly node: TreeNode;
    readonly schema: TreeNodeSchema;
    private readonly initialContext;
    private disposed;
    /**
     * Generation number which is incremented any time we have an edit on the node.
     * Used during iteration to make sure there has been no edits that were concurrently made.
     * @remarks
     * This is updated monotonically by this class when edits are applied.
     * TODO: update this when applying edits to unhydrated trees.
     *
     * If TypeScript supported making this immutable from outside the class without making it readonly from inside, that would be used here,
     * but they only way to do that is add a separate public accessor and make it private, which was deemed not worth the boilerplate, runtime overhead and bundle size.
     */
    generationNumber: number;
    /**
     * Create a TreeNodeKernel which can be looked up with {@link getKernel}.
     *
     * @param initialContext - context from when this node was originally crated.
     * @param innerNode - When unhydrated/raw or marinated the MapTreeNode. FlexTreeNode when cooked.
     * @remarks
     * Exactly one kernel per TreeNode should be created.
     */
    constructor(node: TreeNode, schema: TreeNodeSchema, innerNode: InnerNode, initialContext: Context);
    get context(): Context;
    /**
     * Transition from {@link Unhydrated} to hydrated.
     * Bi-directionally associates the given hydrated TreeNode to the given anchor node.
     * @remarks
     * Happens at most once for any given node.
     * Cleans up mappings to {@link UnhydratedFlexTreeNode} - it is assumed that they are no longer needed once the proxy has an anchor node.
     */
    private hydrate;
    private createHydratedState;
    getStatus(): TreeStatus;
    get events(): Listenable<KernelEvents>;
    dispose(): void;
    isHydrated(): this is {
        anchorNode: AnchorNode;
        context: HydratedContext;
    };
    get anchorNode(): AnchorNode | undefined;
    /**
     * Retrieves the flex node associated with the given target via {@link setInnerNode}.
     * @remarks
     * For {@link Unhydrated} nodes, this returns the MapTreeNode.
     *
     * For hydrated nodes it returns a FlexTreeNode backed by the forest.
     * Note that for "marinated" nodes, this FlexTreeNode exists and returns it: it does not return the MapTreeNode which is the current InnerNode.
     */
    getOrCreateInnerNode(allowFreed?: boolean): InnerNode;
    /**
     * Creates an anchor node and associates it with the given proxy.
     * @privateRemarks
     * Use `forgetters` to cleanup the anchor allocated by this function once the anchor is no longer needed.
     * In practice, this happens when either the anchor node is destroyed, or another anchor to the same node is created by a new flex node.
     *
     * The FlexTreeNode holds a reference to the same anchor, and has a lifetime at least as long as the simple-tree,
     * so this would be unnecessary except for the case of "marinated" nodes, which have an anchor,
     * but might not have a FlexTreeNode.
     * Handling this case is an optimization assuming that this extra anchor reference is cheaper than eagerly creating FlexTreeNodes.
     */
    anchorProxy(anchors: AnchorSet, path: UpPath): AnchorNode;
    /**
     * Retrieves the InnerNode associated with the given target via {@link setInnerNode}, if any.
     * @remarks
     * If `target` is an unhydrated node, returns its UnhydratedFlexTreeNode.
     * If `target` is a cooked node (or marinated but a FlexTreeNode exists) returns the FlexTreeNode.
     * If the target is a marinated node with no FlexTreeNode for its anchor, returns undefined.
     */
    tryGetInnerNode(): InnerNode | undefined;
}
declare const kernelEvents: readonly ["childrenChangedAfterBatch", "subtreeChangedAfterBatch"];
type KernelEvents = Pick<AnchorEvents, (typeof kernelEvents)[number]>;
/**
 * For "cooked" nodes this is a FlexTreeNode thats a projection of forest content.
 * For {@link Unhydrated} nodes this is a MapTreeNode.
 * For "marinated" nodes, some code (ex: getOrCreateInnerNode) returns the FlexTreeNode thats a projection of forest content, and some code (ex: tryGetInnerNode) returns undefined.
 *
 * @remarks
 * Currently MapTreeNode extends FlexTreeNode, and most code which can work with either just uses FlexTreeNode.
 * TODO: Code should be migrating toward using this type to distinguish to two use-cases.
 *
 * TODO: The inconsistent handling of "marinated" cases should be cleaned up.
 * Maybe getOrCreateInnerNode should cook marinated nodes so they have a proper InnerNode?
 */
export type InnerNode = FlexTreeNode | UnhydratedFlexTreeNode;
/**
 * {@inheritdoc proxyToMapTreeNode}
 */
export declare const mapTreeNodeToProxy: WeakMap<UnhydratedFlexTreeNode, TreeNode>;
/**
 * An anchor slot which associates an anchor with its corresponding TreeNode, if there is one.
 * @remarks
 * For this to work, we have to require that there is at most a single view using a given AnchorSet.
 * FlexTree already has this assumption, and we also assume there is a single simple-tree per FlexTree, so this is valid.
 */
export declare const proxySlot: import("../../core/index.js").AnchorSlot<TreeNode>;
/**
 * Retrieves the node associated with the given MapTreeNode node if any.
 */
export declare function tryGetTreeNodeFromMapNode(flexNode: UnhydratedFlexTreeNode): TreeNode | undefined;
export declare function tryDisposeTreeNode(anchorNode: AnchorNode): void;
/**
 * Lookup a TreeNodeSchema from a Hydrated FlexTreeNode.
 * @privateRemarks
 * This provides a way to access simple tree schema from the flex tree without depending on {@link FlexTreeSchema} which is in the process of being removed.
 * This is currently limited to hydrated nodes: this limitation will have to be fixed before {@link FlexTreeSchema} can be fully removed.
 */
export declare function getTreeNodeSchemaFromHydratedFlexNode(flexNode: FlexTreeNode): TreeNodeSchema;
/**
 * Retrieves the flex node associated with the given target via {@link setInnerNode}.
 * @remarks
 * For {@link Unhydrated} nodes, this returns the MapTreeNode.
 *
 * For hydrated nodes it returns a FlexTreeNode backed by the forest.
 * Note that for "marinated" nodes, this FlexTreeNode exists and returns it: it does not return the MapTreeNode which is the current InnerNode.
 */
export declare function getOrCreateInnerNode(treeNode: TreeNode, allowFreed?: boolean): InnerNode;
/**
 * Gets a tree node from an anchor node
 */
export declare function treeNodeFromAnchor(anchorNode: AnchorNode): TreeNode | TreeValue;
export {};
//# sourceMappingURL=treeNodeKernel.d.ts.map