import { Graph } from '@api-client/graph/graph/Graph.js';
import { DataDomainKind } from '../models/kinds.js';
import type { AssociationAddOptions, DeserializationIssue, DeserializationMode, DomainGraphEdge, DomainGraphNodeType, SerializedGraph, DomainSearchCriteria, DomainSearchResult } from './types.js';
import { type DomainNamespaceSchema, DomainNamespace, type NamespaceOrderedItem } from './DomainNamespace.js';
import { type DomainModelSchema, DomainModel } from './DomainModel.js';
import { type DomainEntitySchema, DomainEntity } from './DomainEntity.js';
import { DomainAssociation } from './DomainAssociation.js';
import { DomainProperty, DomainPropertySchema } from './DomainProperty.js';
import { type IThing, Thing } from '../models/Thing.js';
import { DependentModel, type DependentModelSchema, type DomainDependency } from './DependentModel.js';
export interface DataDomainSchema extends DependentModelSchema {
    info: IThing;
    kind: typeof DataDomainKind;
    key: string;
    graph?: SerializedGraph;
    /**
     * The ordered list of fields (namespace and models) in the schema.
     * These only keep references to define the order of these properties
     * in the schema as graph won't do it.
     */
    fields?: NamespaceOrderedItem[];
}
/**
 * Represents the root of a data domain model.
 *
 * The `DataDomain` class serves as the top-level container
 * for a collection of data models, namespaces, entities,
 * properties, and associations. It provides methods for
 * managing and manipulating these data elements, enabling
 * the creation of complex and interconnected data
 * structures.
 *
 * **Key Features:**
 *
 * -   **Root Container:** Holds all data elements within a domain.
 * -   **Graph-Based Structure:** Uses a graph to represent relationships between data elements.
 * -   **Namespace Management:** Supports creating and managing namespaces to organize data models.
 * -   **Data Model Management:** Supports creating and managing data models to group entities.
 * -   **Entity Management:** Supports creating and managing entities, which define the structure of data.
 * -   **Property Management:** Supports creating and managing properties, which define the data elements
 *     within entities.
 * -   **Association Management:** Supports creating and managing associations, which define relationships
 *     between entities.
 * -   **Foreign Domain Support:** Allows registering and integrating data from external domains.
 * -   **Change Notification:** Notifies listeners when changes occur within the data domain.
 *
 * **Usage:**
 *
 * 1.  Create an instance of the `DataDomain`.
 * 2.  Use methods like `addNamespace()`, `addModel()`,
 *     `addEntity()`, `addProperty()`, and `addAssociation()`
 *     to build the data domain structure.
 * 3.  Use methods like `findNamespace()`, `findModel()`,
 *     `findEntity()`, `findProperty()`, and
 *     `findAssociation()` to retrieve data elements.
 * 4.  Use methods like `listNamespaces()`, `listGraphNamespaces()`, `listModels()`,
 *     and `listEntities()` to iterate over collections of
 *     data elements.
 * 5.  Use `registerForeignDomain()` to integrate data from
 *     external domains.
 * 6.  Listen for the `change` event to be notified of
 *     changes within the data domain.
 *
 * **Example:**
 *
 * ```typescript
 * const dataDomain = new DataDomain();
 * const userNamespace = dataDomain.addNamespace({
 *   key: 'userNamespace',
 * });
 * const userModel = userNamespace.addModel({
 *   key: 'userModel',
 * });
 * const userEntity = userModel.addEntity({
 *   key: 'user',
 * });
 * const nameProperty = userEntity.addProperty({
 *   key: 'name',
 *   type: 'string',
 * });
 * ```
 *
 * @fires DataDomain#change {Event} - Fired when the data
 * domain changes.
 *
 * @todo: Implement a mechanism to move an entity to a new
 * parent model.
 */
export declare class DataDomain extends DependentModel {
    #private;
    /**
     * The kind of the domain element.
     */
    kind: typeof DataDomainKind;
    /**
     * The unique key of the domain element.
     */
    key: string;
    /**
     * The graph used to store the data domain structure.
     */
    graph: Graph<unknown, DomainGraphNodeType, DomainGraphEdge>;
    /**
     * The description of the domain property.
     */
    info: Thing;
    /**
     * This is to keep it consistent with the domain elements.
     */
    get domain(): DataDomain;
    /**
     * The ordered list of fields (namespace and models) in the schema.
     * These only keep references to define the order of these properties
     * in the schema as graph won't do it.
     */
    accessor fields: NamespaceOrderedItem[];
    /**
     * The list of issues encountered during deserialization.
     * This is only populated when deserialization fails in lenient mode.
     */
    issues: DeserializationIssue[];
    static createSchema(input?: Partial<DataDomainSchema>): DataDomainSchema;
    /**
     * Creates a new instance of the `DataDomain` class.
     *
     * When creating a new Data Domain arguments should not be set.
     * When restoring a Data Domain from a previous state, you should provide
     * the serialized graph state as well as the same list of dependencies
     * used when the graph was deserialized. Edges to missing dependency nodes
     * will be ignored.
     *
     * @param state The previously serialized state of the graph.
     * @param dependencies An array of foreign data domains to register with this domain.
     */
    constructor(state?: Partial<DataDomainSchema>, dependencies?: DomainDependency[], mode?: DeserializationMode);
    /**
     * Serializes the DataDomain instance to a JSON object.
     * It does not serialize the foreign domain dependencies. The serialized nodes
     * are the ones that are local to this data domain.
     * @returns The serialized data domain ready for storage or transport.
     */
    toJSON(): DataDomainSchema;
    /**
     * This function is used internally by all domain elements to notify that something has changed.
     * Since we want to notify listeners after the operation commits, we use microtask
     * to ensure that the event is dispatched after the current operation.
     */
    notifyChange(): void;
    private removeField;
    /**
     * Checks if this data domain has any fields (namespace and models).
     *
     * @returns True if the data domain has fields.
     * @example
     * ```typescript
     * if (domain.hasFields()) {
     *   // ...
     * }
     * ```
     */
    hasFields(): boolean;
    /**
     * Lists all fields (namespace and models) of this namespace.
     *
     * @returns A generator that yields each `DomainAssociation` or `DomainProperty`.
     * @example
     * ```typescript
     * for (const field of namespace.listFields()) {
     *   console.log(field.key);
     * }
     * ```
     */
    listFields(): Generator<DomainNamespace | DomainModel>;
    /**
     * Adds a new data domain instance to the graph.
     *
     * @param value The partial namespace schema. All missing
     *   values will be filled with default values.
     * @param parent The parent namespace key. If not provided,
     *   the new namespace will be added to the root of the
     *   graph.
     * @returns The created namespace instance.
     * @throws Error When the parent does not exist or is not
     *   a namespace.
     * @example
     * ```typescript
     * const newNamespace = dataDomain.addNamespace({
     *   key: 'newNamespace',
     * });
     * ```
     */
    addNamespace(value?: Partial<DomainNamespaceSchema>, parent?: string): DomainNamespace;
    /**
     * Removes a namespace from the graph.
     *
     * @param key The key of the namespace to remove.
     * @returns The current DataDomain instance.
     * @throws Error When the namespace does not exist.
     * @example
     * ```typescript
     * dataDomain.removeNamespace('userNamespace');
     * ```
     */
    removeNamespace(key: string): this;
    /**
     * Lists all namespaces of this data domain that are direct children of it.
     *
     * Note, it accounts for the order of the namespaces as defined in the `fields` array.
     *
     * @returns A generator that yields each `DomainNamespace`.
     * @example
     * ```typescript
     * for (const ns of domain.listNamespaces()) {
     *   console.log(ns.key);
     * }
     * ```
     */
    listNamespaces(): Generator<DomainNamespace>;
    /**
     * Lists all namespaces in the graph that are part of specified domain.
     *
     * @param namespace The foreign namespace to search in. When not found, it throws an error.
     * @returns A generator that yields each `DomainNamespace`.
     * @throws Error When the foreign domain is not found.
     * @example
     * ```typescript
     * for (const ns of dataDomain.listForeignNamespaces('foreignDomainKey')) {
     *   console.log(ns.key);
     * }
     * ```
     */
    listForeignNamespaces(namespace: string): Generator<DomainNamespace>;
    /**
     * Checks if this data domain has any namespaces.
     *
     * @returns True if the data domain has namespaces.
     * @example
     * ```typescript
     * if (domain.hasNamespaces()) {
     *   // ...
     * }
     * ```
     */
    hasNamespaces(): boolean;
    /**
     * Lists all namespaces in the graph.
     *
     * @param parent The key of the parent namespace. If not
     *   provided, all root namespaces will be listed.
     * @returns A generator that yields each `DomainNamespace`.
     * @example
     * ```typescript
     * for (const ns of dataDomain.listGraphNamespaces()) {
     *   console.log(ns.key);
     * }
     * ```
     */
    listGraphNamespaces(parent?: string): Generator<DomainNamespace>;
    /**
     * Builds a reference key for a domain object.
     *
     * If the namespace is provided and it is different from the domain key,
     * it will return the key in the format `namespace:key`. The foreign namespace
     * must be registered in the domain's dependencies otherwise an error will be thrown.
     *
     * @param key The key of the namespace or model.
     * @param namespace The namespace to search in. When different from the domain key, it looks for a foreign namespace.
     * @returns The reference key in the format `namespace:key` or just `key` if no namespace is provided.
     * @throws Error When the foreign domain is not found.
     * @example
     * ```typescript
     * const refKey = dataDomain.buildReferenceKey('userModel', 'domainKey');
     * ```
     */
    buildReferenceKey(key: string, namespace?: string): string;
    /**
     * Finds a namespace by its key.
     *
     * @param key The key of the namespace to find.
     * @param namespace The namespace to search in. When different from the domain key, it looks for a foreign namespace.
     * @returns The namespace instance or undefined if not
     *   found.
     * @example
     * ```typescript
     * const ns = dataDomain.findNamespace('userNamespace');
     * if (ns) {
     *   console.log(ns.key);
     * }
     * ```
     */
    findNamespace(key: string, namespace?: string): DomainNamespace | undefined;
    /**
     * Moves a namespace to a new parent.
     *
     * @param key The key of the namespace to move.
     * @param parent The new parent namespace key. If
     *   undefined, the namespace will be moved to the root.
     * @returns The current DataDomain instance.
     * @throws Error When the namespace or parent does not
     *   exist, or when a namespace is moved to itself or
     *   its own child.
     * @example
     * ```typescript
     * dataDomain.moveNamespace('userNamespace', 'root');
     * ```
     */
    moveNamespace(key: string, parent?: string): this;
    /**
     * Checks if a namespace is a child of another namespace.
     * @param parentKey The key of the parent namespace.
     * @param childKey The key of the child namespace.
     * @returns True if the namespace is a child of another namespace.
     */
    private isChildOf;
    /**
     * Adds a data model to the graph.
     *
     * @param input The partial data model schema.
     * @param parent The parent namespace key. If not
     *   provided, the new data model will be added to the
     *   root of the graph.
     * @returns The created data model instance.
     * @throws Error When the parent does not exist or is not
     *   a namespace.
     * @example
     * ```typescript
     * const newModel = dataDomain.addModel({
     *   key: 'newModel',
     * });
     * ```
     */
    addModel(input?: Partial<DomainModelSchema>, parent?: string): DomainModel;
    /**
     * Removes a data model from the graph.
     *
     * @param key The key of the data model to remove.
     * @returns The current DataDomain instance.
     * @throws Error When the data model does not exist.
     * @example
     * ```typescript
     * dataDomain.removeModel('userModel');
     * ```
     */
    removeModel(key: string): this;
    /**
     * Lists all models of this data domain that are direct children of it.
     *
     * Note, it accounts for the order of the models as
     * defined in the `fields` array.
     *
     * @returns A generator that yields each `DomainModel`.
     * @example
     * ```typescript
     * for (const model of namespace.listModels()) {
     *   console.log(model.key);
     * }
     * ```
     */
    listModels(): Generator<DomainModel>;
    /**
     * Lists all models in the graph that are part of specified domain.
     *
     * @param namespace The foreign namespace to search in. When not found, it throws an error.
     * @returns A generator that yields each `DomainModel`.
     * @throws Error When the foreign domain is not found.
     * @example
     * ```typescript
     * for (const model of dataDomain.listForeignModels('foreignDomainKey')) {
     *   console.log(model.key);
     * }
     * ```
     */
    listForeignModels(namespace: string): Generator<DomainModel>;
    /**
     * Checks if this data domain has any direct models.
     *
     * @returns True if the data domain has models.
     * @example
     * ```typescript
     * if (domain.hasModels()) {
     *   // ...
     * }
     * ```
     */
    hasModels(): boolean;
    /**
     * Lists all data models in the graph.
     *
     * @param parent The key of the parent namespace. If not
     *   provided, all root data models will be listed.
     * @returns A generator that yields each `DomainModel`.
     * @example
     * ```typescript
     * for (const model of dataDomain.listGraphModels()) {
     *   console.log(model.key);
     * }
     * ```
     */
    listGraphModels(parent?: string): Generator<DomainModel>;
    /**
     * Finds a data model by its key.
     *
     * @param key The key of the data model to find.
     * @param namespace The namespace to search in. When different from the domain key, it looks for a foreign entity.
     * @returns The data model instance or undefined if not
     *   found.
     * @example
     * ```typescript
     * const model = dataDomain.findModel('userModel');
     * if (model) {
     *   console.log(model.key);
     * }
     * ```
     */
    findModel(key: string, namespace?: string): DomainModel | undefined;
    /**
     * Moves a data model to a new parent.
     *
     * @param key The key of the data model to move.
     * @param parent The new parent namespace key. If
     *   undefined, the data model will be moved to the root.
     * @returns The current DataDomain instance.
     * @throws Error When the data model or parent does not
     *   exist, or when a data model is moved to a foreign
     *   domain.
     * @example
     * ```typescript
     * dataDomain.moveModel('userModel', 'newNamespace');
     * ```
     */
    moveModel(key: string, parent?: string): this;
    /**
     * Adds an entity to a data model.
     *
     * @param input The partial entity schema.
     * @param parent The key of the parent data model.
     * @returns The created entity instance.
     * @throws {Error} When the parent does not exist or is not a data model.
     * @example
     * ```typescript
     * const userEntity = dataDomain.addEntity({
     *   key: 'user',
     * }, 'userModel');
     * ```
     */
    addEntity(parent: string, input?: Partial<DomainEntitySchema>): DomainEntity;
    /**
     * Removes an entity from the graph.
     *
     * @param key The key of the entity to remove.
     * @returns The current DataDomain instance.
     * @throws Error When the entity does not exist.
     * @example
     * ```typescript
     * dataDomain.removeEntity('user');
     * ```
     */
    removeEntity(key: string): this;
    /**
     * Lists all entities in a data model, or, if the model key is not provided,
     * all entities in the domain.
     *
     * @param parent The key of the parent data model.
     * @returns A generator that yields each `DomainEntity`.
     * @example
     * ```typescript
     * for (const entity of dataDomain.listEntities('userModel')) {
     *   console.log(entity.key);
     * }
     * ```
     */
    listEntities(parent?: string): Generator<DomainEntity>;
    /**
     * Lists all entities in the graph that are part of specified domain.
     *
     * @param namespace The foreign namespace to search in. When not found, it throws an error.
     * @returns A generator that yields each `DomainEntity`.
     * @throws Error When the foreign domain is not found.
     * @example
     * ```typescript
     * for (const model of dataDomain.listForeignEntities('foreignDomainKey')) {
     *   console.log(model.key);
     * }
     * ```
     */
    listForeignEntities(namespace: string): Generator<DomainEntity>;
    /**
     * Lists all entities in the graph that are not part of this domain.
     */
    listAllForeignEntities(): Generator<DomainEntity>;
    /**
     * Finds an entity by its key.
     *
     * @param key The key of the entity to find.
     * @param namespace The namespace to search in. When different from the domain key, it looks for a foreign entity.
     * @returns The entity instance or undefined if not found.
     * @example
     * ```typescript
     * const entity = dataDomain.findEntity('user');
     * if (entity) {
     *   console.log(entity.key);
     * }
     * ```
     */
    findEntity(key: string, namespace?: string): DomainEntity | undefined;
    /**
     * Moves an entity from one model to another.
     *
     * @param entityKey The key of the entity to move.
     * @param sourceModelKey The key of the source model.
     * @param targetModelKey The key of the target model.
     * @throws Error When the entity, source model, or target model does not exist.
     * @throws Error When the entity is not in the same domain.
     * @throws Error When the source and target models are the same.
     * @throws Error When moving to an unsupported object.
     */
    moveEntity(entityKey: string, sourceModelKey: string, targetModelKey: string): void;
    /**
     * Adds an association between two entities.
     *
     * This function is a shortcut that finds the entity and
     * calls the `addAssociation` method on it.
     *
     * @param source The key of the source entity.
     * @param init The association options.
     * @returns The created association.
     * @throws Error When the source entity does not exist.
     * @example
     * ```typescript
     * const addressAssociation = dataDomain.addAssociation(
     *   'user', { key: 'address' }
     * );
     * ```
     */
    addAssociation(source: string, init?: AssociationAddOptions): DomainAssociation;
    /**
     * Removes an association from the graph.
     *
     * @param key The key of the association to remove.
     * @returns The current DataDomain instance.
     * @throws Error When the association does not exist or
     *   when the parent entity is not found.
     * @example
     * ```typescript
     * dataDomain.removeAssociation('address');
     * ```
     */
    removeAssociation(key: string): this;
    /**
     * Finds an association by its key.
     *
     * @param key The key of the association to find.
     * @param namespace The namespace to search in. When different from the domain key, it looks for a foreign association
     * @returns The association instance or undefined if not
     *   found.
     * @example
     * ```typescript
     * const assoc = dataDomain.findAssociation('address');
     * if (assoc) {
     *   console.log(assoc.key);
     * }
     * ```
     */
    findAssociation(key: string, namespace?: string): DomainAssociation | undefined;
    /**
     * Adds a property to an entity.
     *
     * @param parent The key of the parent entity.
     * @param property The partial property schema.
     * @returns The created property instance.
     * @throws Error When the parent does not exist or is not
     *   an entity.
     * @example
     * ```typescript
     * const nameProperty = dataDomain.addProperty(
     *   'user', { key: 'name', type: 'string' }
     * );
     * ```
     */
    addProperty(parent: string, property?: Partial<DomainPropertySchema>): DomainProperty;
    /**
     * Removes a property from the graph.
     *
     * @param key The key of the property to remove.
     * @returns The current DataDomain instance.
     * @throws Error When the property does not exist or when
     *   the parent entity is not found.
     * @example
     * ```typescript
     * dataDomain.removeProperty('name');
     * ```
     */
    removeProperty(key: string): this;
    /**
     * Finds a property by its key.
     *
     * @param key The key of the property to find.
     * @param namespace The namespace to search in. When different from the domain key, it looks for a foreign property
     * @returns The property instance or undefined if not
     *   found.
     * @example
     * ```typescript
     * const prop = dataDomain.findProperty('name');
     * if (prop) {
     *   console.log(prop.key);
     * }
     * ```
     */
    findProperty(key: string, namespace?: string): DomainProperty | undefined;
    /**
     * Registers a foreign DataDomain.
     *
     * @param domain The foreign DataDomain instance.
     * @param key The unique identifier for the foreign
     *   domain.
     * @param version The version of the foreign domain.
     * @throws Error When a foreign domain with the same key is already registered.
     * @example
     * ```typescript
     * dataDomain.registerForeignDomain(
     *   foreignDomain, 'foreignDomain', '1.0.0'
     * );
     * ```
     */
    registerForeignDomain(domain: DataDomain): void;
    /**
     * Un-registers a foreign DataDomain. It removes all defined by the foreign domain
     * information from the graph.
     * @param key The key of the foreign domain to unregister.
     */
    unregisterForeignDomain(key: string): void;
    /**
     * Finds an entity in a foreign domain.
     *
     * @param entityKey The key of the entity to find.
     * @param domainKey The key of the foreign domain.
     * @returns The entity instance or undefined if not
     *   found.
     * @example
     * ```typescript
     * const foreignUser = dataDomain.findForeignEntity(
     *   'user', 'foreignDomain'
     * );
     * if (foreignUser) {
     *   console.log(foreignUser.key);
     * }
     * ```
     * @deprecated Use `findEntity` with the `namespace` parameter instead.
     * This method is kept for backward compatibility but will be removed in the future.
     */
    findForeignEntity(entityKey: string, domainKey: string): DomainEntity | undefined;
    /**
     * A convenience function to remove an object from the
     * namespace.
     *
     * @param key The key of the object to remove.
     * @param kind The kind of the object to remove.
     * @throws Error when the kind is not known.
     * @example
     * ```typescript
     * dataDomain.removeDomainElement('user', DomainEntityKind);
     * ```
     */
    removeDomainElement(key: string, kind: string): void;
    /**
     * Searches domain nodes by text content and/or node type.
     *
     * This function traverses the graph and filters nodes based on the provided search criteria.
     * It can search through name, displayName, and description fields of domain objects,
     * and optionally filter by specific node types.
     *
     * @param criteria Search criteria including query string/regex and filtering options.
     * @returns An array of search results containing matching nodes and metadata.
     *
     * @example
     * ```typescript
     * // Search for nodes containing "user" in any text field
     * const results = dataDomain.search({ query: 'user' });
     *
     * // Search for entities only
     * const entityResults = dataDomain.search({
     *   nodeTypes: [DomainEntityKind]
     * });
     *
     * // Search for "user" in entities and properties with case-sensitive matching
     * const specificResults = dataDomain.search({
     *   query: 'User',
     *   nodeTypes: [DomainEntityKind, DomainPropertyKind],
     *   caseSensitive: true
     * });
     *
     * // Search using regex pattern
     * const regexResults = dataDomain.search({
     *   query: /^user/i
     * });
     * ```
     */
    search(criteria?: DomainSearchCriteria): DomainSearchResult[];
}
//# sourceMappingURL=DataDomain.d.ts.map