/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { IFluidHandle } from "@fluidframework/core-interfaces";
import { FieldKey, Value, TreeStoredSchema, ValueSchema, FieldStoredSchema, TreeSchemaIdentifier, TreeTypeSet, MapTree, ITreeCursorSynchronous, SchemaData, TreeValue } from "../core";
import { FieldKind } from "./modular-schema";
import { AllowedTypes, FieldSchema, TreeSchema } from "./typed-schema";
import { AllowedTypesToTypedTrees, ApiMode, TypedField, TypedNode } from "./schema-aware";
/**
 * A symbol for the name of the type of a tree in contexts where string keys are already in use for fields.
 * See {@link TreeSchemaIdentifier}.
 * @alpha
 */
export declare const typeNameSymbol: unique symbol;
/**
 * A symbol for the value of a tree node in contexts where string keys are already in use for fields.
 * @alpha
 */
export declare const valueSymbol: unique symbol;
/**
 * @alpha
 * @privateRemarks
 * TODO: remove from package API when old editable-tree API is removed
 */
export declare type PrimitiveValue = string | boolean | number;
/**
 * Checks if a value is a {@link PrimitiveValue}.
 */
export declare function isPrimitiveValue(nodeValue: unknown): nodeValue is PrimitiveValue;
export declare function allowsValue(schema: ValueSchema | undefined, nodeValue: Value): boolean;
export declare function valueSchemaAllows<TSchema extends ValueSchema>(schema: TSchema, nodeValue: Value): nodeValue is TreeValue<TSchema>;
/**
 * Use for readonly view of Json compatible data that can also contain IFluidHandles.
 *
 * Note that this does not robustly forbid non json comparable data via type checking,
 * but instead mostly restricts access to it.
 */
export declare type FluidSerializableReadOnly = IFluidHandle | string | number | boolean | null | readonly FluidSerializableReadOnly[] | {
    readonly [P in string]?: FluidSerializableReadOnly;
};
export declare function isFluidHandle(value: undefined | FluidSerializableReadOnly): value is IFluidHandle;
export declare function assertAllowedValue(value: undefined | FluidSerializableReadOnly): asserts value is Value;
/**
 * @returns the key and the schema of the primary field out of the given tree schema.
 *
 * See note on {@link EmptyKey} for what is a primary field.
 * @alpha
 */
export declare function getPrimaryField(schema: TreeStoredSchema): {
    key: FieldKey;
    schema: FieldStoredSchema;
} | undefined;
export declare function getFieldSchema(field: FieldKey, schema: TreeStoredSchema): FieldStoredSchema;
export declare function getFieldKind(fieldSchema: FieldStoredSchema): FieldKind;
/**
 * @returns all allowed child types for `typeSet`.
 */
export declare function getAllowedTypes(schemaData: SchemaData, typeSet: TreeTypeSet): ReadonlySet<TreeSchemaIdentifier>;
/**
 * @returns all types, for which the data is schema-compatible.
 */
export declare function getPossibleTypes(context: TreeDataContext, typeSet: TreeTypeSet, data: ContextuallyTypedNodeData): TreeSchemaIdentifier[];
/**
 * A symbol used to define a {@link MarkedArrayLike} interface.
 * @alpha
 */
export declare const arrayLikeMarkerSymbol: unique symbol;
/**
 * Can be used to mark a type which works like an array, but is not compatible with `Array.isArray`.
 * @alpha
 */
export interface MarkedArrayLike<TGet, TSet extends TGet = TGet> extends ArrayLikeMut<TGet, TSet> {
    readonly [arrayLikeMarkerSymbol]: true;
    [Symbol.iterator](): IterableIterator<TGet>;
}
/**
 * Can be used to mark a type which works like an array, but is not compatible with `Array.isArray`.
 * @alpha
 */
export interface ReadonlyMarkedArrayLike<T> extends ArrayLike<T> {
    readonly [arrayLikeMarkerSymbol]: true;
    [Symbol.iterator](): IterableIterator<T>;
}
/**
 * `ArrayLike` numeric indexed access, but writable.
 *
 * @remarks
 * Note that due to language limitations, this also allows reading as TSet.
 * This is why `TSet extends TGet` is required.
 *
 * See https://github.com/microsoft/TypeScript/issues/43826.
 * @alpha
 */
export interface ArrayLikeMut<TGet, TSet extends TGet = TGet> extends ArrayLike<TGet> {
    [n: number]: TSet;
}
/**
 * Content of a tree which needs external schema information to interpret.
 *
 * This format is intended for concise authoring of tree literals when the schema is statically known.
 *
 * Once schema aware APIs are implemented, they can be used to provide schema specific subsets of this type.
 * @alpha
 */
export declare type ContextuallyTypedNodeData = ContextuallyTypedNodeDataObject | PrimitiveValue | readonly ContextuallyTypedNodeData[] | MarkedArrayLike<ContextuallyTypedNodeData>;
/**
 * Content of a field which needs external schema information to interpret.
 *
 * This format is intended for concise authoring of tree literals when the schema is statically known.
 *
 * Once schema aware APIs are implemented, they can be used to provide schema specific subsets of this type.
 * @alpha
 */
export declare type ContextuallyTypedFieldData = ContextuallyTypedNodeData | undefined;
/**
 * Information needed to interpret a subtree described by {@link ContextuallyTypedNodeData} and {@link ContextuallyTypedFieldData}.
 * @alpha
 * TODO:
 * Currently being exposed at the package level which also requires us to export MapTree at the package level.
 * Refactor the FieldGenerator to use JsonableTree instead of MapTree, and convert them internally.
 */
export interface TreeDataContext {
    /**
     * Schema for the document which the tree will be used in.
     */
    readonly schema: SchemaData;
    /**
     * Procedural data generator for fields.
     * Fields which provide generators here can be omitted in the input contextually typed data.
     *
     * @remarks
     * TODO:
     * For implementers of this which are not pure (like identifier generation),
     * order of invocation should be made consistent and documented.
     * This will be important for identifier elision optimizations in tree encoding for session based identifier generation.
     */
    fieldSource?(key: FieldKey, schema: FieldStoredSchema): undefined | FieldGenerator;
}
/**
 * Generates field content for a MapTree on demand.
 * @alpha
 * TODO:
 * Currently being exposed at the package level which also requires us to export MapTree at the package level.
 * Refactor the FieldGenerator to use JsonableTree instead of MapTree, and convert them internally.
 */
export declare type FieldGenerator = () => MapTree[];
/**
 * Checks the type of a `ContextuallyTypedNodeData`.
 */
export declare function isArrayLike(data: ContextuallyTypedFieldData): data is readonly ContextuallyTypedNodeData[] | ReadonlyMarkedArrayLike<ContextuallyTypedNodeData>;
/**
 * Checks the type of a `ContextuallyTypedNodeData`.
 * @alpha
 */
export declare function isContextuallyTypedNodeDataObject(data: ContextuallyTypedNodeData | undefined): data is ContextuallyTypedNodeDataObject;
/**
 * Object case of {@link ContextuallyTypedNodeData}.
 * @alpha
 */
export interface ContextuallyTypedNodeDataObject {
    /**
     * Value stored on this node.
     */
    readonly [valueSymbol]?: Value;
    /**
     * The type of the node.
     * If this node is well-formed, it must follow this schema.
     */
    readonly [typeNameSymbol]?: string;
    /**
     * Fields of this node, indexed by their field keys.
     *
     * Allow explicit undefined for compatibility with EditableTree, and type-safety on read.
     */
    [key: FieldKey]: ContextuallyTypedFieldData;
    /**
     * Fields of this node, indexed by their field keys as strings.
     *
     * Allow unbranded field keys as a convenience for literals.
     */
    [key: string]: ContextuallyTypedFieldData;
}
/**
 * Construct a tree from ContextuallyTypedNodeData.
 *
 * TODO: this should probably be refactored into a `try` function which either returns a Cursor or a SchemaError with a path to the error.
 * @alpha
 */
export declare function cursorFromContextualData(context: TreeDataContext, typeSet: TreeTypeSet, data: ContextuallyTypedNodeData): ITreeCursorSynchronous;
/**
 * Strongly typed {@link cursorFromContextualData} for a TreeSchema
 * @alpha
 */
export declare function cursorForTypedTreeData<T extends TreeSchema>(context: TreeDataContext, schema: T, data: TypedNode<T, ApiMode.Simple>): ITreeCursorSynchronous;
/**
 * Strongly typed {@link cursorFromContextualData} for AllowedTypes.
 * @alpha
 */
export declare function cursorForTypedData<T extends AllowedTypes>(context: TreeDataContext, schema: T, data: AllowedTypesToTypedTrees<ApiMode.Simple, T>): ITreeCursorSynchronous;
/**
 * Construct a tree from ContextuallyTypedNodeData.
 *
 * TODO: this should probably be refactored into a `try` function which either returns a Cursor or a SchemaError with a path to the error.
 * TODO: migrate APIs which take arrays of cursors to take cursors in fields mode.
 */
export declare function cursorsFromContextualData(context: TreeDataContext, field: FieldStoredSchema, data: ContextuallyTypedNodeData | undefined): ITreeCursorSynchronous[];
/**
 * Strongly typed {@link cursorsFromContextualData} for a FieldSchema
 * @alpha
 */
export declare function cursorsForTypedFieldData<T extends FieldSchema>(context: TreeDataContext, schema: T, data: TypedField<T, ApiMode.Flexible>): ITreeCursorSynchronous[];
/**
 * Construct a MapTree from ContextuallyTypedNodeData.
 *
 * TODO: this should probably be refactored into a `try` function which either returns a MapTree or a SchemaError with a path to the error.
 * TODO: test suite.
 *
 * @remarks
 * This version is only exported as a more testable entry point than `cursorFromContextualData` which keeps the use of `MapTree` as an implementation detail.
 * This should not be reexported from the parent module.
 */
export declare function applyTypesFromContext(context: TreeDataContext, typeSet: TreeTypeSet, data: ContextuallyTypedNodeData): MapTree;
/**
 * Construct a MapTree from ContextuallyTypedNodeData.
 *
 * TODO: this should probably be refactored into a `try` function which either returns a MapTree or a SchemaError with a path to the error.
 * TODO: test suite.
 *
 * @remarks
 * This version is only exported as a more testable entry point than `cursorsFromContextualData` which keeps the use of `MapTree` as an implementation detail.
 * This should not be reexported from the parent module.
 */
export declare function applyFieldTypesFromContext(context: TreeDataContext, field: FieldStoredSchema, data: ContextuallyTypedFieldData): MapTree[];
/**
 * Content to use for a field.
 *
 * When used, this content will be deeply copied into the tree, and must comply with the schema.
 *
 * The content must follow the {@link Multiplicity} of the {@link FieldKind}:
 * - use a single cursor for an `optional` or `value` field;
 * - use array of cursors for a `sequence` field;
 *
 * TODO: this should allow a field cursor instead of an array of cursors.
 * TODO: Make this generic so a variant of this type that allows placeholders for detached sequences to consume.
 * @alpha
 */
export declare type NewFieldContent = ITreeCursorSynchronous | readonly ITreeCursorSynchronous[] | ContextuallyTypedFieldData;
/**
 * Convert NewFieldContent into ITreeCursor array.
 */
export declare function normalizeNewFieldContent(context: TreeDataContext, schema: FieldStoredSchema, content: NewFieldContent): readonly ITreeCursorSynchronous[];
//# sourceMappingURL=contextuallyTyped.d.ts.map