/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { type ChangeAtomId, type ChangeAtomIdRangeMap, type ChangesetLocalId, type FieldKey, type FieldKindIdentifier, type RevisionInfo, type RevisionTag } from "../../core/index.js";
import { RangeMap, type Brand, type RangeQueryResult, type TupleBTree } from "../../util/index.js";
import type { TreeChunk } from "../chunked-forest/index.js";
import type { CrossFieldTarget } from "./crossFieldQueries.js";
export type RebaseVersion = 1 | 2;
export interface ModularChangeset extends HasFieldChanges {
    readonly rebaseVersion: RebaseVersion;
    /**
     * The numerically highest `ChangesetLocalId` used in this changeset.
     * If undefined then this changeset contains no IDs.
     */
    readonly maxId?: ChangesetLocalId;
    /**
     * The revisions included in this changeset, ordered temporally (oldest to newest).
     * Undefined for anonymous changesets.
     * Should never be empty.
     */
    readonly revisions?: readonly RevisionInfo[];
    readonly fieldChanges: FieldChangeMap;
    /**
     * Maps from this changeset's canonical ID for a node (see comment on node aliases) to the changes for that node.
     */
    readonly nodeChanges: ChangeAtomIdBTree<NodeChangeset>;
    readonly rootNodes: RootNodeTable;
    /**
     * Maps from this changeset's canonical ID for a node to the ID for the field which contains that node,
     * or the detach ID, if this node is detached.
     */
    readonly nodeToParent: ChangeAtomIdBTree<NodeLocation>;
    /**
     * Maps from a node ID to another ID for the same node.
     * If a node ID used in this changeset has no entry in this table, then it is the canonical ID for that node.
     * The aliases form a set of trees, where the root of each tree is a canonical ID.
     *
     * When composing changesets with different canonical IDs for the same node,
     * one of those IDs becomes the canonical ID for the composition, while the other is added to this table as an alias.
     *
     * Node aliases are preserved when composing changesets so we can avoid having to find and update all changed node IDs
     * in the field IDs in nodeToParent and crossFieldKeys.
     */
    readonly nodeAliases: ChangeAtomIdBTree<NodeId>;
    readonly crossFieldKeys: CrossFieldKeyTable;
    /**
     * The number of constraint violations that apply to the input context of the changeset, i.e., before this change is applied.
     * If this count is greater than 0, it will prevent the changeset from being applied.
     */
    readonly constraintViolationCount?: number;
    /**
     * The number of constraint violations that apply to the revert of the changeset. If this count is greater than 0, it will
     * prevent the changeset from being reverted or undone.
     */
    readonly constraintViolationCountOnRevert?: number;
    readonly builds?: ChangeAtomIdBTree<TreeChunk>;
    readonly destroys?: ChangeAtomIdBTree<number>;
    readonly refreshers?: ChangeAtomIdBTree<TreeChunk>;
}
export interface RootNodeTable {
    oldToNewId: ChangeAtomIdRangeMap<ChangeAtomId>;
    newToOldId: ChangeAtomIdRangeMap<ChangeAtomId>;
    nodeChanges: ChangeAtomIdBTree<NodeId>;
    /**
     * Maps from input context detach ID to the field where the node was last attached.
     * There should be an entry for every detach ID referenced in `oldToNewId` or `nodeChanges`.
     */
    detachLocations: ChangeAtomIdRangeMap<FieldId>;
    /**
     * Maps from the output root ID of a node to the output detach location of that node.
     * This is only guaranteed to contain entries for nodes which have an output detach location
     * which is different from their location in the input context.
     */
    outputDetachLocations: ChangeAtomIdRangeMap<FieldId>;
}
export type ChangeAtomIdBTree<V> = TupleBTree<ChangeAtomIdKey, V>;
export type ChangeAtomIdKey = [RevisionTag | undefined, ChangesetLocalId];
export declare function getFromChangeAtomIdMap<T>(map: ChangeAtomIdBTree<T>, id: ChangeAtomId): T | undefined;
export declare function rangeQueryChangeAtomIdMap<T>(map: ChangeAtomIdBTree<T>, id: ChangeAtomId, count: number): RangeQueryResult<T | undefined>;
export declare function setInChangeAtomIdMap<T>(map: ChangeAtomIdBTree<T>, id: ChangeAtomId, value: T): boolean;
export type CrossFieldRangeTable<T> = RangeMap<CrossFieldKey, T>;
export type CrossFieldKeyTable = CrossFieldRangeTable<FieldId>;
export declare function newCrossFieldRangeTable<V>(): CrossFieldRangeTable<V>;
export interface CrossFieldKey extends ChangeAtomId {
    readonly target: CrossFieldTarget;
}
export interface CrossFieldKeyRange {
    key: CrossFieldKey;
    count: number;
}
export interface FieldId {
    readonly nodeId: NodeId | undefined;
    readonly field: FieldKey;
}
export interface FieldParent {
    readonly field: FieldId;
    readonly root?: undefined;
}
export interface RootParent {
    readonly field?: undefined;
    readonly root: ChangeAtomId;
}
export type NodeLocation = FieldParent | RootParent;
export interface DetachLocation {
    field: FieldId;
    atomId: ChangeAtomId | undefined;
}
/**
 */
export interface NodeExistsConstraint {
    violated: boolean;
}
/**
 * Changeset for a subtree rooted at a specific node.
 */
export interface NodeChangeset extends HasFieldChanges {
    /** Keeps track of whether node exists constraint has been violated by this change */
    readonly nodeExistsConstraint?: NodeExistsConstraint;
    /** Keeps track of whether node exists constraint will be violated when this change is reverted */
    readonly nodeExistsConstraintOnRevert?: NodeExistsConstraint;
}
export type NodeId = ChangeAtomId;
export interface HasFieldChanges {
    readonly fieldChanges?: FieldChangeMap;
}
export type FieldChangeMap = Map<FieldKey, FieldChange>;
export interface FieldChange {
    fieldKind: FieldKindIdentifier;
    change: FieldChangeset;
}
export type FieldChangeset = Brand<unknown, "FieldChangeset">;
//# sourceMappingURL=modularChangeTypes.d.ts.map