/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { ImplementationError } from "@matter/general";
import { DefinitionError, ElementTag, Specification } from "../common/index.js";
import { AnyElement, BaseElement } from "../elements/index.js";
import { Children } from "./Children.js";
import type { MatterModel } from "./MatterModel.js";
import { Resource } from "./Resource.js";
/**
 * Thrown when model API is used incorrectly.
 */
export declare class StructuralModelError extends ImplementationError {
}
/**
 * A "model" is a class that implements runtime functionality associated with the corresponding element type.
 *
 * @template E the element type this model implements
 */
export declare abstract class Model<E extends BaseElement = BaseElement, C extends Model = Model<BaseElement, any>> {
    #private;
    abstract readonly tag: ElementTag;
    type?: string;
    isSeed?: boolean;
    /**
     * Indicates that an element defines a datatype.
     */
    isType?: boolean;
    /**
     * Normally {@link base} performs lookup based on {@link type}.  Setting this field short circuits this resolution.
     *
     * The operational base also enables resolution from the operational base's tree.  This enables resolution on
     * operational models that are not installed in a parent hierarchy.
     *
     * We set the operational base when freezing the model.
     */
    operationalBase?: Model | null;
    /**
     * This is like {@link operationalBase} except for the element's shadow.
     */
    operationalShadow?: Model | null;
    /**
     * Indicates whether the corresponding element is supported by an implementation.
     *
     * This is an operational implementation hint and does not override conformance.
     */
    operationalIsSupported?: boolean;
    get id(): E["id"];
    set id(value: E["id"]);
    get name(): string;
    set name(value: string);
    /**
     * Did validation find errors?
     */
    get valid(): boolean;
    /**
     * The path ("." delimited) in the Matter tree.
     *
     * This is informational and generally tries to adhere to JS API conventions.
     */
    get path(): string;
    /**
     * Determine if this model resides in the global namespace.
     */
    get isGlobal(): boolean;
    /**
     * The structural parent.  This is the model for the element that contains this element's definition.
     */
    get parent(): Model | undefined;
    /**
     * The structural root.  This is the MatterModel that owns this model.
     */
    get root(): MatterModel | undefined;
    set parent(parent: Model | undefined);
    /**
     * Allows subclasses to pull a working ID from an alternate source.
     */
    get effectiveId(): E["id"];
    /**
     * Get a string that uniquely identifies this model.  This is normally the effective ID but some models require a
     * generated identifier.
     */
    get key(): string | undefined;
    /**
     * Obtain a discriminator that differentiates different models with the same name
     */
    get discriminator(): string | undefined;
    /**
     * Children of models are always models.
     */
    get children(): Children<C>;
    get hasChildren(): boolean;
    /**
     * Set the children of the model.
     */
    set children(children: Children.InputIterable<C>);
    /**
     * Factory support.
     */
    static types: Record<string, Model.ConcreteType>;
    /**
     * Add a new model implementation.
     */
    static register(this: Model.ConcreteType): void;
    /**
     * All possible tags for registered models of this type.
     */
    static get tags(): ElementTag[];
    /**
     * In some circumstances the base type can be inferred.  This inference happens here.
     *
     * Does not recurse so only returns the direct base type.
     */
    get effectiveType(): string | undefined;
    /**
     * Get a model for my base type as defined by {@link type}, if any.
     */
    get base(): Model | undefined;
    /**
     * Get shadow model, if any.  A "shadow" is an element in my parent's inheritance hierarchy that I override.
     */
    get shadow(): Model | undefined;
    /**
     * Get the first global base type.  This may have semantic meaning more specific than the base primitive type.
     */
    get globalBase(): Model<BaseElement, Model<BaseElement, any>> | undefined;
    /**
     * A local or parent xref.
     */
    get effectiveXref(): Specification.CrossReference | undefined;
    /**
     * The set of tags from which this model may derive.
     */
    get allowedBaseTags(): ElementTag[];
    /**
     * Obtain the "is supported" flag from inheritance.
     */
    get effectiveIsSupported(): boolean | undefined;
    /**
     * Update a subset of fields.
     *
     * Only allows for updates to element properties.  Recurses to children.
     */
    patch(values: Model.Patch<E>): void;
    /**
     * Determine whether this element applies to a specific revision.
     */
    appliesTo(revision: Specification.Revision): boolean;
    /**
     * Create a model for an element.
     */
    static create(definition: AnyElement): Model<BaseElement, Model<BaseElement, any>>;
    /**
     * Retrieve all models of a specific element type from local scope.
     *
     * @param type model class or a predicate object
     * @param key filters to models matching a specific type
     */
    all<T extends Model>(type: Model.Type<T>, key?: number | string): T[];
    /**
     * Retrieve a specific child by ID or name.
     */
    get<T extends Model>(type: Model.Type<T>, key: number | string): T | undefined;
    /**
     * Retrieve a model of a specific type from the ownership hierarchy.
     */
    owner<T extends Model>(constructor: Model.Type<T>): T | undefined;
    /**
     * Record a validation error for this model.
     */
    error(code: string, message: string): void;
    /**
     * Convert model to JSON.
     */
    toJSON(): E;
    /**
     * Convert to non-class structure.
     */
    valueOf(): E;
    /**
     * Convert to elemental form.
     */
    toElement(omitResources?: boolean, extra?: Record<string, unknown>): E;
    /**
     * Apply a function to all tree elements.
     */
    visit(visitor: (model: Model) => boolean | void): boolean | undefined;
    /**
     * Visit this model and each of its ancestors.
     */
    forEachAncestor(fn: (model: Model) => boolean | void): void;
    /**
     * Find all children that reference a specific type.
     */
    references(type: Model): Model<BaseElement, Model<BaseElement, any>>[];
    /**
     * Search the inheritance chain for a child property.
     */
    member(key: Children.Selector, allowedTags?: ElementTag[]): Model | undefined;
    /**
     * Access a member that must exist.
     */
    require<T extends Model>(type: Model.ConcreteType<T>, key: Children.Selector): T;
    /**
     * Does this model derive from another?
     */
    instanceOf(other: Model | AnyElement): boolean;
    /**
     * Clone the model.  This deep copies all descendant child models but not other properties.
     */
    clone<This extends Model>(this: This): This;
    /**
     * Create an operational extension of the model.  This creates a new model that inherits from this model for
     * operational purposes.
     */
    extend<This extends Model>(this: This, properties?: Partial<Model.Definition<This>>, ...children: Model.ChildDefinition<Model>[]): This;
    constructor(definition: Model.Definition<Model<E>>, ...children: Model.TaggedDefinition<C>[]);
    /**
     * Finalize the model hierarchy rooted at this model.
     *
     * When using a model as operational schema we implement various optimizations that assume the schema is immutable.
     * This function enforces that assumption and caches a few values that only make sense with frozen schema.
     *
     * To make changes to a final model use {@link clone}.
     */
    finalize(): void;
    get isFinal(): boolean | undefined;
    toString(): string;
    get resource(): Resource | undefined;
    set resource(resource: Resource | undefined);
    get description(): string | undefined;
    set description(description: string | undefined);
    get details(): string | undefined;
    set details(details: string | undefined);
    get xref(): Specification.CrossReference | undefined;
    set xref(xref: Specification.CrossReference | undefined);
    get errors(): DefinitionError[] | undefined;
    set errors(errors: DefinitionError[] | undefined);
    get asOf(): Specification.Revision | undefined;
    set asOf(asOf: Specification.Revision | undefined);
    get until(): Specification.Revision | undefined;
    set until(until: Specification.Revision | undefined);
    get matchTo(): {
        id?: string | number;
        name?: string;
    } | undefined;
    set matchTo(matchTo: {
        id?: string | number;
        name?: string;
    } | undefined);
    get localResource(): Resource;
    get hasLocalResource(): boolean;
}
export declare namespace Model {
    /**
     * Obtain the element type of a model type.
     */
    type ElementOf<T extends Model> = T extends Model<infer E extends BaseElement> ? E : never;
    /**
     * Obtain the child type of a model type.
     */
    type ChildOf<T extends Model> = T extends Model<any, infer C extends Model> ? C : never;
    /**
     * Constructor input.
     *
     * In most places elements and models are interchangeable on input.
     */
    type Definition<T extends Model> = (BaseElement.Properties<ElementOf<T>> & {
        parent?: Model;
        operationalBase?: Model;
        operationalShadow?: Model;
        operationalIsSupported?: boolean;
    }) | T;
    /**
     * An object that may be used in some places where a model is required.
     *
     * This is either a model, a class constructor or a DecoratorContext.
     */
    type Source = Model | NewableFunction;
    /**
     * Tagged input.  Like {@link Definition} but for places where model type is not implied.
     */
    type TaggedDefinition<T extends Model> = (ElementOf<T> & {
        operationalBase?: Model;
        operationalShadow?: Model;
    }) | T;
    /**
     * Input model for children.
     */
    type ChildDefinition<T extends Model> = TaggedDefinition<ChildOf<T>>;
    /**
     * A model constructor.
     */
    type Type<T extends Model = Model> = abstract new (definition: any) => T;
    /**
     * A model constructor for a specific element type.
     */
    type ConcreteType<T extends Model = Model> = (new (definition: any) => T) & {
        Tag: ElementTag;
        requiresId?: boolean;
    };
    /**
     * A patch to a model tree.
     */
    type Patch<T extends BaseElement> = Omit<Partial<T>, "children" | "tag"> & {
        children?: (Patch<Exclude<T["children"], undefined>[number]> | undefined)[];
    };
    type Properties<T extends BaseElement.Properties = BaseElement.Properties> = T & {
        operationalBase?: Model;
        operationalShadow?: Model;
    };
    type LookupPredicate<T extends Model> = Type<T> | {
        type: Type<T>;
        test: (model: Model) => boolean;
    };
    type PropertyValidation = {
        name: string;
        type: string | (new (...args: any[]) => any) | {
            [key: string | number]: any;
        } | undefined;
        required?: boolean;
        nullable?: boolean;
        values?: {
            [name: string]: any;
        };
    };
}
//# sourceMappingURL=Model.d.ts.map