import { IHost, INopeINopeConnectivityOptions } from "./nopeConnectivityManager.interface";
import { INopeCore } from "./nopeCore.interface";
import { INopeDescriptor } from "./nopeDescriptor.interface";
import { IEventAdditionalData, IEventCallback, INopeEventEmitter, INopeObserver } from "./nopeEventEmitter.interface";
import { INopeModule, INopeModuleDescription } from "./nopeModule.interface";
import { INopeObservable } from "./nopeObservable.interface";
import { INopePromise } from "./nopePromise.interface";
import { ValidDefaultSelectors } from "./nopeRpcManager.interface";
export type IGenerateInstanceCallback<I extends INopeModule> = () => Promise<I>;
export type IGenerateRemoteInstanceCallback<I extends INopeModule> = (dispatcher: INopeDispatcher, description: INopeModuleDescription, ...args: any[]) => Promise<I>;
export type IGenerateRemoteInstanceForOtherDispatcherCallback<I extends INopeModule> = (dispatcher: INopeDispatcher, identifier: string, ...args: any[]) => Promise<I>;
export type IValidPromise<T> = Promise<T> | INopePromise<T>;
export type INopeDispatcherOptions = {
    /**
     * The Id of the Dispatcher
     *
     * @author M.Karkowski
     * @type {string}
     */
    id?: string;
    /**
     * The default-selector to select the service providers
     *
     * @author M.Karkowski
     * @type {ValidDefaultSelectors}
     */
    defaultSelector?: ValidDefaultSelectors;
    /**
     * Flag to force using the service provider selector
     * functionalities.
     *
     * @author M.Karkowski
     * @type {boolean}
     */
    forceUsingSelectors?: boolean;
    /**
     * Flag to ensure, that every path used is corrcet and could be
     * used as variable in another system.
     *
     * @author M.Karkowski
     * @type {boolean}
     */
    forceUsingValidVarNames?: boolean;
    /**
     * Flag to indicate, whether methodes with the call {@link nope.exportAsNopeService} are
     * provided by the instance or not.
     */
    useExportedServices?: boolean;
} & INopeINopeConnectivityOptions;
export interface IHostOverview extends IHost {
    dispatchers: {
        id: string;
        pid: number | string;
    }[];
    instances: INopeModuleDescription[];
    services: {
        name: string;
        schema: INopeDescriptor;
    }[];
}
export interface IDispatcherConstructor {
    new (options: INopeDispatcherOptions, _generateEmitter: <T>() => INopeEventEmitter<T>, _generateObservable: <T>() => INopeObservable<T>): INopeDispatcher;
}
/**
 * # NoPE - Dispatcher
 *
 * The NoPE-Dispatcher is designed as Layer between the different Modules / Dispatchers. They allow distributed computing or just a simple ***Service oriented Architecture*** (*SOA*). A dispatcher is used to link the modules, share data and events and provide a remote procedure call (rpc) interface.
 *
 * ## Building Blocks of a Dispatcher:
 *
 * | element | description |
 * |-|-|
 * | `connectivityManager` | establishes a connection to other dispatchers and manages the status of the remotely connected dispatchers. It checks their health and removes dead dispatchers. |
 * | `eventDistributor` | shares events accross the network (or internally). You can use this element to listen for specific events. The subscription to those events allows `mqtt`-patterns. Additionaly, you are allowed to emit event on specific topics, or pattern based topics |
 * | `dataDistributor` | shares data accross the network (or internally). In comperisson to events, data is persistent and is available all the time. You can use this sub-module to listen for specific data-changes (install data-hooks), pull specific data or push data. You can pull / push data using a `mqtt`-pattern based path. |
 * | `rpcManager` | Used to perform `remote procedure calls` (see [here](https://de.wikipedia.org/wiki/Remote_Procedure_Call)). The manager keeps track of the available services. You must use the sub-module to register/unregister (new) services. |
 * | `instanceManager` | Used to create/dispose (remote) instances. The manager keeps track of the available instances in the network, allows to create `wrappers` for those instances. You must use the sub-module to register/unregister (new) instances. To allow the system to provide a service for creating instances of as specific type, you can provide a generator and provide it as `service`. |
 * @export
 * @interface INopeDispatcher
 */
export interface INopeDispatcher extends INopeCore {
    readonly options: INopeDispatcherOptions;
    /**
     * Pushs the desired data into the system.
     * @param path The path to the Data.
     * @param content The Content to Push
     * @param options The Options during pushing
     */
    pushData<T = unknown>(path: string, content: T, options: IEventAdditionalData): void;
    /**
     * Helper to pull some data from the system.
     * @param path The path to the Data.
     * @param _default The value to use if no data has been found. If not provided an error is thrown. Defaults to None.
     */
    pullData<T = unknown, D = null>(path: string, _default?: D): T;
    /**
     * Helper to subscribe to specific events.
     * @param event Name of the relevant event
     * @param subscription the Callback to use.
     */
    subscribeToEvent<T = unknown>(event: string, subscription: IEventCallback<T>): INopeObserver;
    /**
     * Emits an event with the given name. All
     * event-subscriber, where the topic matches
     * will receive this notification.
     * @param eventName
     * @param data
     */
    emitEvent(eventName: string, data: any): any;
    /**
     * Receive the "instances" | "services" | "properties" | "events"
     * which matches with the given pattern. Therefore the user provides
     * the pattern and tyle.
     *
     * @author M.Karkowski
     * @param {string} pattern Pattern to query the provided type.
     * @param {("instances" | "services" | "properties" | "events")} type Type which should be querried
     * @return {string[]} List of the matching items.
     * @memberof INopeDispatcher
     */
    query(pattern: string, type: "instances" | "services" | "properties" | "events"): string[];
    /**
     * Function used to dispose the Dispatcher. This will
     * dispose all instances an remove the them. They wont
     * be available in the NoPE-Network.
     *
     * @author M.Karkowski
     * @return {Promise<void>}
     * @memberof INopeDispatcher
     */
    dispose(): Promise<void>;
}
