/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { IFluidHandle } from "@fluidframework/core-interfaces";
import { FlexAllowedTypes, FlexObjectNodeSchema, FlexTreeNodeSchema, FlexTreeSequenceField, FlexTreeNode, FlexTreeField } from "../feature-libraries/index.js";
import { TreeValue } from "../core/index.js";
import { type TreeNodeSchema as TreeNodeSchemaClass, type InsertableTypedNode } from "./schemaTypes.js";
import { TreeArrayNode } from "./treeArrayNode.js";
import { Unhydrated, TreeNode } from "./types.js";
/**
 * 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>;
/**
 * Retrieve the associated proxy for the given field.
 * */
export declare function getProxyForField(field: FlexTreeField): TreeNode | TreeValue | undefined;
/**
 * A symbol for storing TreeNodeSchemaClass on FlexTreeNode's schema.
 */
export declare const simpleSchemaSymbol: unique symbol;
export declare function getClassSchema(schema: FlexTreeNodeSchema): TreeNodeSchemaClass | undefined;
export declare function getOrCreateNodeProxy(flexNode: FlexTreeNode): TreeNode | TreeValue;
/**
 * @param flexNode - underlying tree node which this proxy should wrap.
 * @param allowAdditionalProperties - If true, setting of unexpected properties will be forwarded to the target object.
 * Otherwise setting of unexpected properties will error.
 * @param customTargetObject - Target object of the proxy.
 * If not provided an empty collection of the relevant type is used for the target and a separate object created to dispatch methods.
 * If provided, the customTargetObject will be used as both the dispatch object and the proxy target, and therefor must provide needed functionality depending on the schema kind.
 */
export declare function createNodeProxy(flexNode: FlexTreeNode, allowAdditionalProperties: boolean, targetObject?: object): TreeNode | TreeValue;
/**
 * @param allowAdditionalProperties - If true, setting of unexpected properties will be forwarded to the target object.
 * Otherwise setting of unexpected properties will error.
 * @param customTargetObject - Target object of the proxy.
 * If not provided `{}` is used for the target.
 */
export declare function createObjectProxy<TSchema extends FlexObjectNodeSchema>(schema: TSchema, allowAdditionalProperties: boolean, targetObject?: object): TreeNode;
/**
 * Given a array node proxy, returns its underlying LazySequence field.
 */
export declare const getSequenceField: <TTypes extends FlexAllowedTypes>(arrayNode: TreeArrayNode) => FlexTreeSequenceField<TTypes>;
/**
 * PropertyDescriptorMap used to build the prototype for our array node dispatch object.
 */
export declare const arrayNodePrototypeProperties: PropertyDescriptorMap;
export declare const mapStaticDispatchMap: PropertyDescriptorMap;
/**
 * Create a proxy to a {@link TreeObjectNode} that is backed by a raw object node (see {@link createRawNode}).
 * @param schema - the schema of the object node
 * @param content - the content to be stored in the raw node.
 * A copy of content is stored, the input `content` is not modified and can be safely reused in another call to {@link createRawObjectProxy}.
 * @param allowAdditionalProperties - If true, setting of unexpected properties will be forwarded to the target object.
 * Otherwise setting of unexpected properties will error.
 * @param customTargetObject - Target object of the proxy.
 * If not provided `{}` is used for the target.
 * @remarks
 * Because this proxy is backed by a raw node, it has the same limitations as the node created by {@link createRawNode}.
 * Most of its properties and methods will error if read/called.
 */
export declare function createRawNodeProxy(schema: FlexTreeNodeSchema, content: InsertableTypedNode<TreeNodeSchemaClass> & object, allowAdditionalProperties: boolean, target?: object): Unhydrated<TreeNode>;
type ProxyHydrator = (flexNode: FlexTreeNode | undefined) => void;
/** The result returned by {@link extractFactoryContent} and its related helpers. */
interface ExtractedFactoryContent<out T = FactoryContent> {
    /** The content with the factory subtrees replaced. */
    readonly content: T;
    /**
     * A function which walks all factory-created object that underwent replacement/extraction.
     * Before hydration, those objects are unusable (see {@link createRawObjectProxy}).
     * However, after the content is fully inserted into the tree the `hydrateProxies` function may be invoked in order to update the contents of these objects such that they become a mirror of the content in the tree.
     * This must be done before any calls to {@link getOrCreateNodeProxy} so that the "edit node to proxy" mapping is correctly updated (see {@link setFlexNode}).
     */
    readonly hydrateProxies: ProxyHydrator;
}
/**
 * Given a content tree that is to be inserted into the shared tree, replace all subtrees that were created by factories
 * (via {@link SharedTreeObjectFactory.create}) with the content that was passed to those factories.
 * @param content - the content being inserted which may be, and/or may contain, factory-created content
 * @param insertedAtIndex - if the content being inserted is array node content, this must be the index in the array node at which the content is being inserted
 * @returns the result of the content replacement and a {@link ExtractedFactoryContent.hydrateProxies} function which must be invoked if present.
 * @remarks
 * This functions works recursively.
 * Factory-created objects that are nested inside of the content passed to other factory-created objects, and so on, will be in-lined.
 * This function also adds the hidden {@link typeNameSymbol} of each object schema to the output.
 * @example
 * ```ts
 * const x = foo.create({
 *   a: 3, b: bar.create({
 *     c: [baz.create({ d: 5 })]
 *   })
 * });
 * const y = extractFactoryContent(x);
 * y === {
 *   [typeNameSymbol]: "foo", a: 3, b: {
 *     [typeNameSymbol]: "bar", c: [{ [typeNameSymbol]: "baz", d: 5 }]
 *  }
 * }
 * ```
 */
export declare function extractFactoryContent(input: InsertableContent, insertedAtIndex?: number): ExtractedFactoryContent;
/**
 * Content which can be used to build a node.
 * @remarks
 * Can contain unhydrated nodes, but can not be an unhydrated node at the root.
 */
export type FactoryContent = IFluidHandle | string | number | boolean | null | ReadonlyMap<string, InsertableContent> | readonly InsertableContent[] | {
    readonly [P in string]?: InsertableContent;
};
/**
 * Content which can be inserted into a tree.
 */
export type InsertableContent = Unhydrated<TreeNode> | FactoryContent;
export {};
//# sourceMappingURL=proxies.d.ts.map