/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Access, Aspect, Constraint } from "../aspects/index.js";
import { ElementTag, Specification } from "../common/index.js";
import { AnyElement } from "../elements/index.js";
import { Children } from "../models/Children.js";
import type { CommandModel, MatterModel, Model, ScopeModel, ValueModel } from "../models/index.js";
/**
 * This class performs lookups of models in the scope of a specific model.  We use a class so the lookup can maintain
 * state and guard against circular references.
 *
 * Any logic that requires traversal of a multi-model ownership or inheritance should use this class.
 *
 */
export declare class ModelTraversal {
    #private;
    /**
     * Perform an operation with iteration tracking.  If iteration depth limit
     */
    operation<T>(operator: () => T, toDismiss?: Model): T;
    /**
     * Perform an operation with a model dismissed from consideration for type lookup.
     */
    operationWithDismissal<T>(toDismiss: Model | undefined, operator: () => T): T;
    /**
     * Determine the type for a model.  This is the string name of the base model.  Usually this is simply the type
     * field but we infer the type in some cases where it is not supplied explicitly:
     *
     * - Children of maps and enums are uints of corresponding size
     * - Models that shadow another model in their parent's inheritance effectively inherit from the shadow so have
     *   their own name as the type name
     */
    getTypeName(model: Model | undefined): string | undefined;
    /**
     * Find the model in my inheritance hierarchy that has semantic meaning. This will be the first inherited model with
     * a metatype.
     */
    findMetabase(model: Model | undefined): Model | undefined;
    /**
     * Find the model a model derives from, if any.
     */
    findBase(model: Model | undefined): Model | undefined;
    /**
     * Find the first global model this model derives from, if any.
     */
    findGlobalBase(model: Model | undefined): Model | undefined;
    /**
     * Determine whether this model derives from another.
     */
    instanceOf(model: Model | undefined, other: Model | AnyElement | undefined): boolean;
    /**
     * Find an xref from this model or a parent.
     */
    findXref(model: Model | undefined): Specification.CrossReference | undefined;
    /**
     * Find the model this model derives from that has children, if any.
     */
    findDefiningModel(model: ValueModel | undefined): ValueModel | undefined;
    /**
     * Find a child in the parent's inheritance hierarchy with the same tag and ID/name.
     */
    findShadow(model: Model | undefined): Model | undefined;
    /**
     * Get an aspect that reflects extension of any shadowed aspects.  Note that this searches the parent's inheritance
     * and the model's inheritance. This is because aspects can be inherited by overriding an element in the parent or
     * by direct type inheritance.  Aspects in shadowed elements take priority as they are presumably more specific.
     */
    findAspect<T extends Aspect, N extends string, M extends Model & {
        [n in N]: T;
    }>(model: M | undefined, name: N, factory: new (definition: undefined) => T): T | undefined;
    /**
     * Constraint aspects are specialized because we infer constraint fields that are referenced in other models.
     */
    findConstraint(model: ValueModel, field?: "value" | "min" | "max"): Constraint | undefined;
    /**
     * Access aspects are specialized because access controls are inherited from the owner if not otherwise defined.
     *
     * That means access controls may come from 5 places, in order of priority:
     *
     *   1. The model itself
     *   2. A shadowed model in the owner hierarchy
     *   3. An overridden model in the model's class hierarchy
     *   4. A model in the parent hierarchy
     *   5. Access.Default
     *
     * This method uses {@link findAspect} for 1-3 then extends the result with 4 & 5 as necessary until
     * {@link Access.complete} is true.
     */
    findAccess(model: ValueModel | undefined, VM: typeof ValueModel): Access;
    /**
     * Search inherited scope for a named member.
     */
    findMember(scope: Model | undefined, key: Children.Selector, allowedTags?: ElementTag[]): Model | undefined;
    /**
     * Search inherited scope for a bit definition.
     */
    findBitDefinition(scope: Model | undefined, bit: number): import("../models/FieldModel.js").FieldModel | undefined;
    /**
     * Search inherited and structural type scope for a named type.
     */
    findType(owner: Model | undefined, name: string, tag: ElementTag): Model | undefined;
    /**
     * Generic qualified path resolution.  Walks scope hierarchy searching for a dotted path.
     *
     * {@link scope} is the starting point for the search — the equivalent of "cwd" were this a filesystem.
     *
     * The {@link match} closure determines how each path segment resolves within a candidate parent.  It receives the
     * segment name, the parent model to search, and whether this is the leaf (final) segment.  For type resolution,
     * the leaf filters by element tag.  For member resolution, this walks inheritance via member().
     *
     * {@link options.boundary}, if provided, is a predicate that stops the parent walk.  When a scope matches the
     * boundary, its inherited scopes are still searched but its parent is not.  After all scopes within the boundary
     * are exhausted, {@link options.outerResolve} is called as a fallback.
     *
     * {@link options.outerResolve}, if provided, is the outermost fallback resolver — called after all natural scopes
     * (within the boundary) are exhausted.  It receives the full path and the boundary scope (the last scope searched
     * before the walk stopped).
     */
    findQualified(scope: Model | undefined, path: string[], match: (name: string, parent: Model, isLeaf: boolean) => Model | undefined, options?: {
        boundary?: (scope: Model) => boolean;
        outerResolve?: (path: string[], boundaryScope: Model | undefined) => Model | undefined;
    }): Model | undefined;
    /**
     * Similar to findType but operates with a qualified type name.
     *
     * Unlike findType, a qualified type may reference an element parented by any other, not just those within
     * ScopeModels.
     *
     * Delegates to {@link findQualified}.  Intermediate segments match by name only; the leaf segment filters by
     * element tag.
     */
    findQualifiedType(scope: Model | undefined, path: string[], tag: ElementTag): Model | undefined;
    /**
     * Find the response model for a command.
     */
    findResponse(command: CommandModel): CommandModel | undefined;
    /**
     * Find all children of a node that reference a specific type.
     */
    findReferences(scope: Model | undefined, type: Model | undefined): Model[];
    /**
     * Find an owning model of a specific type.
     */
    findOwner<T extends Model>(constructor: Model.Type<T>, model: Model | undefined): T | undefined;
    /**
     * Find the root model.
     */
    findRoot(model: Model | undefined): Model | undefined;
    /**
     * Visit all nodes in the model tree.
     */
    visit(model: Model, visitor: (model: Model) => boolean | void): boolean | undefined;
    /**
     * Visit all nodes in the inheritance hierarchy until the visitor returns false.
     */
    visitInheritance(model: Model | undefined, visitor: (model: Model) => boolean | void): boolean | undefined;
    /**
     * Find the parent for this model.
     */
    findParent(model?: Model): Model<import("../elements/BaseElement.js").BaseElement, Model<import("../elements/BaseElement.js").BaseElement, any>> | undefined;
    /**
     * Find an owner that defines type scope for a model.
     */
    findScope(model?: Model): ScopeModel | undefined;
    /**
     * If a model is not owned by a MatterModel, global resolution won't work.  This model acts as a fallback to work
     * around this.
     */
    static fallbackRoot: MatterModel | undefined;
    /**
     * This is a cheap hack to optimize analysis of large static models.  It temporarily memoizes key operations.
     *
     * It's not a huge win but does speed up model validation by approximately 50%
     */
    static memoize(fn: () => void): void;
}
//# sourceMappingURL=ModelTraversal.d.ts.map