/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { type FieldKey, type FieldKindIdentifier, type TreeNodeSchemaIdentifier, type TreeStoredSchema, type ValueSchema } from "../../core/index.js";
/**
 * Discriminated union (keyed on `mismatch`) of discrepancies between a view and stored schema.
 * @remarks
 *
 * 1. FieldDiscrepancy
 *
 * `FieldDiscrepancy` represents the differences between two `TreeFieldStoredSchema` objects. It consists of
 * three types of incompatibilities:
 *
 * - FieldKindDiscrepancy: Indicates the differences in `FieldKindIdentifier` between two `TreeFieldStoredSchema`
 * objects (e.g., optional, required, sequence, etc.).
 * - AllowedTypesDiscrepancy: Indicates the differences in the allowed child types between the two schemas.
 * - ValueSchemaDiscrepancy: Specifically indicates the differences in the `ValueSchema` of two
 * `LeafNodeStoredSchema` objects.
 *
 * 2. NodeDiscrepancy
 *
 * `NodeDiscrepancy` represents the differences between two `TreeNodeStoredSchema` objects and includes:
 *
 * - NodeKindDiscrepancy: Indicates the differences in the types of `TreeNodeStoredSchema` (currently supports
 * `ObjectNodeStoredSchema`, `MapNodeStoredSchema`, and `LeafNodeStoredSchema`).
 * - NodeFieldsDiscrepancy: Indicates the `FieldDiscrepancy` of `TreeFieldStoredSchema` within two
 * `TreeNodeStoredSchema`. It includes an array of `FieldDiscrepancy` instances in the `differences` field.
 *
 * When comparing two nodes for compatibility, it only makes sense to compare their fields if the nodes are of
 * the same kind (map, object, leaf).
 *
 * 3. Discrepancy
 *
 * Discrepancy consists of both `NodeDiscrepancy` and `FieldDiscrepancy`, representing any kind of
 * schema differences. See {@link getAllowedContentDiscrepancies} for more details about how we process it
 * and the ordering.
 */
export type Discrepancy = FieldDiscrepancy | NodeDiscrepancy;
export type NodeDiscrepancy = NodeKindDiscrepancy | NodeFieldsDiscrepancy;
/**
 * A discrepancy in the declaration of a field.
 */
export type FieldDiscrepancy = AllowedTypeDiscrepancy | FieldKindDiscrepancy | ValueSchemaDiscrepancy;
/**
 * Information about where a field discrepancy is located within a collection of schema.
 */
export interface FieldDiscrepancyLocation {
    /**
     * The {@link TreeNodeSchemaIdentifier} that contains the discrepancy.
     *
     * Undefined iff the discrepancy is part of the root field schema.
     */
    identifier: TreeNodeSchemaIdentifier | undefined;
    /**
     * The {@link FieldKey} for the field that contains the discrepancy.
     * Undefined when:
     * - the discrepancy is part of the root field schema
     * - the discrepancy is for 'all fields' of a map node
     */
    fieldKey: FieldKey | undefined;
}
/**
 * A discrepancy in the allowed types of a field.
 *
 * @remarks
 * This reports the symmetric difference of allowed types in view/stored to enable more efficient checks for compatibility
 */
export interface AllowedTypeDiscrepancy extends FieldDiscrepancyLocation {
    mismatch: "allowedTypes";
    /**
     * List of allowed type identifiers in viewed schema which are not allowed in stored schema
     */
    view: TreeNodeSchemaIdentifier[];
    /**
     * List of allowed type identifiers in stored schema which are not allowed in view schema
     */
    stored: TreeNodeSchemaIdentifier[];
}
export interface FieldKindDiscrepancy extends FieldDiscrepancyLocation {
    mismatch: "fieldKind";
    view: FieldKindIdentifier;
    stored: FieldKindIdentifier;
}
export interface ValueSchemaDiscrepancy {
    identifier: TreeNodeSchemaIdentifier;
    mismatch: "valueSchema";
    view: ValueSchema | undefined;
    stored: ValueSchema | undefined;
}
export interface NodeKindDiscrepancy {
    identifier: TreeNodeSchemaIdentifier;
    mismatch: "nodeKind";
    view: SchemaFactoryNodeKind | undefined;
    stored: SchemaFactoryNodeKind | undefined;
}
export interface NodeFieldsDiscrepancy {
    identifier: TreeNodeSchemaIdentifier;
    mismatch: "fields";
    differences: FieldDiscrepancy[];
}
type SchemaFactoryNodeKind = "object" | "leaf" | "map";
/**
 * Finds and reports discrepancies between a view schema and a stored schema.
 *
 * See documentation on {@link Discrepancy} for details of possible discrepancies.
 * @remarks
 * This function does not attempt to distinguish between equivalent representations of a node/field involving extraneous never trees.
 * For example, a Forbidden field with allowed type set `[]` is equivalent to an optional field with allowed type set `[]`,
 * as well as an optional field with an allowed type set containing only unconstructable types.
 *
 * It is up to the caller to determine whether such discrepancies matter.
 */
export declare function getAllowedContentDiscrepancies(view: TreeStoredSchema, stored: TreeStoredSchema): Iterable<Discrepancy>;
/**
 * @remarks
 *
 * This function uses incompatibilities to determine if changes to a document schema are backward-compatible, i.e., it determines
 * whether the `view` schema allows a superset of the documents that the `stored` schema allows.
 * According to the policy of schema evolution, `isRepoSuperset` supports three types of changes:
 * 1. Adding an optional field to an object node.
 * 2. Expanding the set of allowed types for a field.
 * 3. Relaxing a field kind to a more general field kind.
 *
 * Notes: We expect isRepoSuperset to return consistent results with allowsRepoSuperset. However, currently there are some scenarios
 * where the inconsistency will occur:
 *
 * - Different Node Kinds: If a and b have different node kinds (e.g., a is an objectNodeSchema and b is a mapNodeSchema),
 * `isRepoSuperset` will determine that a can never be the superset of b. In contrast, `allowsRepoSuperset` will continue
 * validating internal fields.
 */
export declare function isRepoSuperset(view: TreeStoredSchema, stored: TreeStoredSchema): boolean;
/**
 * A linear extension of a partially-ordered set of `T`s. See:
 * https://en.wikipedia.org/wiki/Linear_extension
 *
 * The linear extension is represented as a lookup from each poset element to its index in the linear extension.
 */
export type LinearExtension<T> = Map<T, number>;
/**
 * A realizer for a partially-ordered set. See:
 * https://en.wikipedia.org/wiki/Order_dimension
 */
export type Realizer<T> = LinearExtension<T>[];
/**
 * A realizer for the partial order of field kind relaxability.
 *
 * It seems extremely likely that this partial order will remain dimension 2 over time (i.e. the set of allowed relaxations can be visualized
 * with a [dominance drawing](https://en.wikipedia.org/wiki/Dominance_drawing)), so this strategy allows efficient comarison between field kinds
 * without excessive casework.
 *
 * Hasse diagram for the partial order is shown below (lower fields can be relaxed to higher fields):
 * ```
 * sequence
 *    |
 * optional
 *    |    \
 * required forbidden
 *    |
 * identifier
 * ```
 */
export declare const fieldRealizer: Realizer<FieldKindIdentifier>;
export declare const PosetComparisonResult: {
    readonly Less: "<";
    readonly Greater: ">";
    readonly Equal: "=";
    readonly Incomparable: "||";
};
type PosetComparisonResult = (typeof PosetComparisonResult)[keyof typeof PosetComparisonResult];
export declare function comparePosetElements<T>(a: T, b: T, realizer: Realizer<T>): PosetComparisonResult;
export declare function posetLte<T>(a: T, b: T, realizer: Realizer<T>): boolean;
export {};
//# sourceMappingURL=discrepancies.d.ts.map