/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import type { ErasedType } from "@fluidframework/core-interfaces";
import { type WithType, typeNameSymbol } from "./schemaTypes.js";
import { type FlexTreeNode, type MapTreeNode } from "../feature-libraries/index.js";
/**
 * Type alias to document which values are un-hydrated.
 *
 * Un-hydrated values are nodes produced from schema's create functions that haven't been inserted into a tree yet.
 *
 * Since un-hydrated nodes become hydrated when inserted, strong typing can't be used to distinguish them.
 * This no-op wrapper is used instead.
 * @public
 */
export type Unhydrated<T> = T;
/**
 * A non-{@link NodeKind.Leaf|leaf} SharedTree node. Includes objects, arrays, and maps.
 *
 * @remarks
 * Base type which all nodes implement.
 *
 * This can be used as a type to indicate/document values which should be tree nodes.
 * Runtime use of this class object (for example when used with `instanceof` or extending it), is not currently supported.
 *
 * Instances of tree nodes must be created by opening an existing document, inserting values into the document,
 * or by using the constructors and create functions of {@link TreeNodeSchema} produced by {@link SchemaFactory}.
 * @privateRemarks
 * This is a class not an interface to enable stricter type checking (see {@link TreeNode.#brand})
 * and some runtime enforcement of schema class policy (see the the validation in the constructor).
 * This class is however only `type` exported not value exported, preventing the class object from being used,
 * similar to how interfaces work.
 *
 * Not all node implementations include this in their prototype chain (some hide it with a proxy),
 * and thus cause the default/built in `instanceof` to return false despite our type checking and all other APIs treating them as TreeNodes.
 * This class provides a custom `Symbol.hasInstance` to fix `instanceof` for this class and all classes extending it.
 * For now the type-only export prevents use of `instanceof` on this class (but allows it in subclasses like schema classes).
 * @sealed @public
 */
export declare abstract class TreeNode implements WithType {
    #private;
    /**
     * Adds a type symbol for stronger typing.
     * @privateRemarks
     * Subclasses provide more specific strings for this to get strong typing of otherwise type compatible nodes.
     */
    abstract get [typeNameSymbol](): string;
    /**
     * Provides `instanceof` support for testing if a value is a `TreeNode`.
     * @remarks
     * For more options, like including leaf values or narrowing to collections of schema, use `is` or `schema` from {@link TreeNodeApi}.
     * @privateRemarks
     * Due to type-only export, this functionality is not available outside the package.
     */
    static [Symbol.hasInstance](value: unknown): value is TreeNode;
    /**
     * Provides `instanceof` support for all schema classes with public constructors.
     * @remarks
     * For more options, like including leaf values or narrowing to collections of schema, use `is` or `schema` from {@link TreeNodeApi}.
     * @privateRemarks
     * Despite type-only export, this functionality is available outside the package since it is inherited by subclasses.
     */
    static [Symbol.hasInstance]<TSchema extends abstract new (...args: any[]) => TreeNode>(this: TSchema, value: unknown): value is InstanceType<TSchema>;
    protected constructor();
}
/**
 * Check if the prototype derived's prototype chain contains `base`.
 * @param derived - prototype to check
 * @param base - prototype to search for
 * @returns true iff `base` is in the prototype chain starting at `derived`.
 */
export declare function inPrototypeChain(derived: object | null, base: object): boolean;
/**
 * Class which all {@link TreeNode}s must extend.
 * Since this is not exported, it allows robust detection of attempts to create TreeNodes which do not go through SchemaFactory which is the only place which exposes classes that extend this.
 *
 * This has static members which schema classes can override to provide schema specific functionality.
 * These static members are only intended to be used / overridden by code within this package, and are used by the various node kinds.
 * Access to these static members has to be done via `this.constructor.staticMember` to support the overrides, and thus can only be used in the constructor, after the base constructor has been invoked.
 */
export declare abstract class TreeNodeValid<TInput> extends TreeNode {
    /**
     * Schema classes can override this to control what happens at the end of the constructor.
     * The return value from this is returned from the constructor, allowing substituting a proxy if desired.
     *
     * This is not simply done in the derived constructor to enable:
     * - this class to access the value which is being returned before it's returned from the constructor.
     * - the derived class to be provided the input `FlexTreeNode` without relying on a field on the node to hold it.
     */
    protected static prepareInstance<T>(this: typeof TreeNodeValid<T>, instance: TreeNodeValid<T>, input: FlexTreeNode): TreeNodeValid<T>;
    /**
     * Schema classes must override to provide an implementation of RawTreeNode construction.
     */
    protected static buildRawNode<T>(this: typeof TreeNodeValid<T>, instance: TreeNodeValid<T>, input: T): MapTreeNode;
    /**
     * Schema classes can override to provide a callback that is called once when the first node is constructed.
     * This is a good place to perform extra validation and cache schema derived data needed for the implementation of the node.
     */
    protected static oneTimeSetup<T>(this: typeof TreeNodeValid<T>): void;
    /**
     * The most derived constructor (the one invoked with the `new` operator, not a parent class constructor invoked with as `super`) used to construct an instance of this type.
     * @remarks
     * Captured when an instance is constructed.
     *
     * Used to ensure that some derived class (which must override this member, defaulting it to `undefined`) is only instantiated with a single "most derived" class (the constructor actually invoked the the user with `new`).
     *
     * Typically this is override in the class that statically implements {@link TreeNodeSchema} to enforce that all nodes using that schema use the same class and not different subclasses of it.
     *
     * Also used to detect if oneTimeSetup has run.
     *
     * @privateRemarks
     * This defaults to TreeNodeValid, which is used to trigger an error if not overridden in the derived class.
     *
     * The value of this on TreeNodeValid must only be overridden by base classes and never modified.
     * Ways to enforce this immutability prevent it from being overridden,
     * so code modifying constructorCached should be extra careful to avoid accidentally modifying the base/inherited value.
     */
    protected static constructorCached: typeof TreeNodeValid | undefined;
    constructor(input: TInput | InternalTreeNode);
}
/**
 * A node type internal to `@fluidframework/tree`.
 * @remarks
 * This type is used in the construction of {@link TreeNode} as an implementation detail, but leaks into the public API due to how schema are implemented.
 * @privateRemarks
 * A {@link FlexTreeNode}. Includes {@link RawTreeNode}s.
 * @sealed @public
 */
export interface InternalTreeNode extends ErasedType<"@fluidframework/tree.InternalTreeNode"> {
}
export declare function toFlexTreeNode(node: InternalTreeNode): FlexTreeNode;
//# sourceMappingURL=types.d.ts.map