import { IThing, Thing } from '../models/Thing.js';
import { IDataAssociation, DataAssociation, AssociationTarget } from './DataAssociation.js';
import { IDataEntity, DataEntity } from './DataEntity.js';
import { IDataModel, DataModel } from './DataModel.js';
import { IDataProperty, DataProperty } from './DataProperty.js';
import { DataNamespaceKind, DataModelKind } from '../models/kinds.js';
type ItemKind = typeof DataNamespaceKind | typeof DataModelKind;
interface IDataDefinitions {
    models?: IDataModel[];
    entities?: IDataEntity[];
    properties?: IDataProperty[];
    associations?: IDataAssociation[];
    namespaces?: IDataNamespace[];
    tags?: string[];
    /**
     * The list of foreign namespaces associated with this namespace.
     */
    foreign?: ForeignNamespace[];
}
interface DataDefinitions {
    models: DataModel[];
    entities: DataEntity[];
    properties: DataProperty[];
    associations: DataAssociation[];
    namespaces: DataNamespace[];
    /**
     * Common for the entire root namespace tags.
     * These are kept separately so the UI can generate autocomplete for tags.
     */
    tags: string[];
    /**
     * The list of foreign namespaces associated with this namespace.
     */
    foreign?: ForeignNamespace[];
}
/**
 * Data definition for a foreign namespace.
 * Each foreign namespace is resolved to a specific version.
 * This makes sure that the local data are always referencing an existing
 * entity as breaking changes should be resolved when upgrading a version.
 */
interface ForeignNamespace {
    key: string;
    version: string;
}
interface IDataNamespaceParent {
    kind: typeof DataNamespaceKind;
    /**
     * The key of the namespace.
     */
    key: string;
    /**
     * The ordered list of items in this namespace.
     */
    items: IDataItem[];
    /**
     * The data namespace description.
     */
    info: IThing;
}
/**
 * Data namespace is a logical description of the hierarchy in the data.
 */
export interface IDataNamespace extends IDataNamespaceParent {
    /**
     * The list of definitions used in the namespace.
     */
    definitions: IDataDefinitions;
}
/**
 * Data item is a reference to an object in the top namespace definitions
 * to the namespace items.
 */
export interface IDataItem {
    /**
     * The kind of the item.
     */
    kind: ItemKind;
    /**
     * The identifier in the `definitions` array of the namespace.
     */
    key: string;
}
declare class DataNamespaceParent {
    kind: string;
    key: string;
    /**
     * The ordered list of items in this namespace.
     */
    items: DataItem[];
    /**
     * The description of the data namespace.
     */
    info: Thing;
    /**
     * When a namespace is a sub-namespace this is the reference to the
     * root namespace with all definitions.
     */
    root?: DataNamespace;
    constructor(root?: DataNamespace);
    /**
     * @returns The parent namespace of this namespace. It returns `undefined` when this is the root namespace.
     */
    getParent(): DataNamespace | undefined;
    /**
     * Adds a data namespace to the structure.
     * @param init The name of the namespace to add, namespace's schema, or instance.
     */
    addNamespace(init: string | IDataNamespace | DataNamespace): DataNamespace;
    /**
     * Lists namespaces that are in this namespace items.
     */
    listNamespaces(): DataNamespace[];
    /**
     * Lists namespaces that are in this namespace items.
     */
    listDataModels(): DataModel[];
    /**
     * @returns The root of the namespaces tree. It might be the same object.
     */
    getRoot(): DataNamespace;
    /**
     * Removes self from the parent namespace with all data models.
     * This does noting for the root namespace.
     */
    remove(): void;
}
export declare class DataItem implements IDataItem {
    kind: ItemKind;
    key: string;
    /**
     * A reference to the top level namespace.
     */
    private root;
    static isDataItem(input: unknown): boolean;
    static dataNamespace(root: DataNamespace, key: string): DataItem;
    static dataModel(root: DataNamespace, key: string): DataItem;
    /**
     * @param root The top-most data namespace.
     * @param input The project item definition used to restore the state.
     */
    constructor(root: DataNamespace, input: string | IDataItem);
    new(init: IDataItem): void;
    toJSON(): IDataItem;
    getItem(): DataNamespace | DataModel | undefined;
}
/**
 * Data namespace is a logical description of the hierarchy in the data.
 */
export declare class DataNamespace extends DataNamespaceParent {
    definitions: DataDefinitions;
    /**
     * The list of foreign namespaces.
     * This is used to find entities from foreign namespaces.
     * Values here are treated as read only (objects can be frozen).
     *
     * This should be set by the application and the namespace will do
     * nothing to populate this value.
     */
    foreign: DataNamespace[];
    /**
     * Creates a new data namespace from a name.
     * @param name The name to set.
     */
    static fromName(name: string, root?: DataNamespace): DataNamespace;
    static definitions(): DataDefinitions;
    constructor(input?: string | IDataNamespace, root?: DataNamespace);
    new(init: IDataNamespace): void;
    toJSON(): IDataNamespace;
    /**
     * Checks if this is the root namespace.
     * @returns True if this is the root namespace.
     */
    isRoot(): boolean;
    /**
     * Finds a parent namespace for the given namespace.
     * @param key The namespace key to find the parent for.
     * @returns The parent namespace or undefined when the namespace does not exist. It may return the root namespace.
     */
    findParent(key: string): DataNamespace | undefined;
    /**
     * Adds a data namespace to the structure.
     * @param init The name of the namespace to add, namespace's schema, or instance.
     * @param parent The optional key of the parent namespace to add the new namespace to.
     */
    addNamespace(init: string | IDataNamespace | DataNamespace, parent?: string): DataNamespace;
    /**
     * Finds a namespace in the definitions.
     * @param key The key of the namespace to find.
     * @returns The namespace definition or undefined when not found.
     */
    findNamespace(key: string): DataNamespace | undefined;
    /**
     * Finds a namespace and calls the `remove()` on it.
     * @param key The key of the namespace to find.
     */
    removeNamespace(key: string): void;
    /**
     * Adds a data model to a namespace.
     * @param init The name of the data model to add, data model's schema, or its instance.
     * @param parent The optional key of the parent namespace to add the new data model to.
     */
    addDataModel(init: string | IDataModel | DataModel, parent?: string): DataModel;
    /**
     * Finds a data model in the definitions.
     * @param key The key of the data model to find.
     * @returns The data model definition or undefined when not found.
     */
    findDataModel(key: string): DataModel | undefined;
    /**
     * Finds a data model and calls the `remove()` on it.
     * @param key The key of the data model to find.
     */
    removeDataModel(key: string): void;
    /**
     * @returns The graph of associations where keys are the source
     * entities and the value is the list of all target entities.
     */
    associationGraph(): Record<string, string[]>;
    /**
     * Prints out all associations from one entity to another through all entities that may be in between.
     *
     * @param from The key of the from entity
     * @param to The key of the target entity
     * @param g The graph generated with `associationGraph()`
     * @param path The current list of entity ids. Do not set this, it is for the recursive processing of the graph.
     * @param visited The list of visited paths to avoid cycles.
     *  Do not set this, it is for the recursive processing of the graph.
     */
    associationPath(from: string, to: string, g: Record<string, string[]>, path?: string[], visited?: Set<string>): Generator<string[]>;
    /**
     * Scans all associations for foreign namespaces and returns
     * the list of all namespaces used in the association graph.
     * This will never add this namespace's key.
     *
     * This function should be used to read keys for all related
     * namespaces through associations.
     *
     * @returns All keys of foreign namespaces.
     */
    computeForeignNamespaceKeys(): string[];
    /**
     * Finds an entity in this namespace.
     * @param key The key of the entity to find.
     */
    findEntity(key: string): DataEntity | undefined;
    /**
     * Finds a property by its key.
     * @param key The key of the property to find
     * @returns The property or undefined if not found.
     */
    findProperty(key: string): DataProperty | undefined;
    /**
     * Finds an association by its key.
     * @param key The key of the property to find
     * @returns The property or undefined if not found.
     */
    findAssociation(key: string): DataAssociation | undefined;
    /**
     * Searches for entities for association targets.
     * This is a helper function to discover entities in the current and foreign namespaces.
     *
     * @param targets The list of targets
     * @returns A list of entities. An `undefined` is put at the index where an entity cannot be found
     */
    findAssociatedEntities(targets: AssociationTarget[]): (DataEntity | undefined)[];
    /**
     * Finds an associated entity in the current or foreign namespace.
     * This is a helper function to discover entities in the current and foreign namespaces.
     *
     * @param key The key of the entity to find.
     * @param namespace The optional namespace to search in.
     * If not set, the current namespace is used.
     * This is used to find entities in foreign namespaces.
     * @returns The entity or undefined if not found.
     */
    findAssociatedEntity(key: string, namespace?: string): DataEntity | undefined;
    addForeign(ns: DataNamespace): void;
    removeForeign(ns: DataNamespace): void;
    hasForeignNamespace(key: string): boolean;
}
export {};
//# sourceMappingURL=DataNamespace.d.ts.map