import { AwilixContainer } from "awilix";
import * as Debug from "debug";
import { BehaviorSubject, Observable, Subject } from "rxjs";
import { ErrorChain } from "../lib/error";
import { Environment } from "./environment";
import { ELogLevel, ILogMessage, ILogMetadata } from "./log";
import { EMetricType, IMetricTags } from "./metric";
import { Module } from "./module";
/** Command line arguments interface. */
export interface IContainerArguments {
    /** Non-option arguments. */
    arguments: string[];
    /** All remaining options. */
    options: object;
}
/** Container error codes. */
export declare enum EContainerError {
    Up = "ContainerError.Up",
    Down = "ContainerError.Down",
    ModuleRegistered = "ContainerError.ModuleRegistered"
}
/** Container error class. */
export declare class ContainerError extends ErrorChain {
    constructor(code: EContainerError, cause?: Error, context?: object);
}
/** Container log message interface. */
export interface IContainerLogMessage {
    level: ELogLevel;
    message: ILogMessage;
    metadata: ILogMetadata;
    args: any[];
}
/** Log message class for stream of module logs. */
export declare class ContainerLogMessage implements IContainerLogMessage {
    readonly level: ELogLevel;
    readonly message: ILogMessage;
    readonly metadata: ILogMetadata;
    readonly args: any[];
    constructor(level: ELogLevel, message: ILogMessage, metadata: ILogMetadata, args: any[]);
}
/** Container metric message interface. */
export interface IContainerMetricMessage {
    type: EMetricType;
    name: string;
    value: any;
    tags: IMetricTags;
    args: any[];
}
/** Metric message class for stream of module metrics. */
export declare class ContainerMetricMessage implements IContainerMetricMessage {
    readonly type: EMetricType;
    readonly name: string;
    readonly value: any;
    readonly tags: IMetricTags;
    readonly args: any[];
    constructor(type: EMetricType, name: string, value: any, tags: IMetricTags, args: any[]);
}
/** Container log names. */
export declare enum EContainerLog {
    Up = "Container.Up",
    Down = "Container.Down"
}
/** Container scope keys. */
export declare enum EContainerScope {
    /** Container reference name resolved internally by modules. */
    Container = "Container"
}
/**
 * Container class.
 * Wrapper around awilix library.
 */
export declare class Container {
    /** Required container name, used to namespace modules. */
    readonly name: string;
    /** Optional container environment. */
    readonly environment: Environment;
    /** Optional command line arguments. */
    readonly argv: IContainerArguments;
    /** Root container. */
    readonly container: AwilixContainer;
    /** Observable module state. */
    readonly modules$: BehaviorSubject<{
        [key: string]: boolean;
    }>;
    /** Array of registered module names. */
    get moduleNames(): string[];
    /** Array of registered modules. */
    get modules(): Module[];
    /** Container module logs. */
    readonly logs$: Subject<ContainerLogMessage>;
    /** Container module metrics. */
    readonly metrics$: Subject<ContainerMetricMessage>;
    /** Module debug interface. */
    readonly debug: Debug.IDebugger;
    /** Creates a new container in proxy resolution mode. */
    constructor(
    /** Required container name, used to namespace modules. */
    name: string, 
    /** Optional container environment. */
    environment?: Environment, 
    /** Optional command line arguments. */
    argv?: IContainerArguments);
    /** Create scoped container from root container. */
    createScope(): AwilixContainer;
    /**
     * Register a module in container.
     * Throws an error if module of name is already registered.
     */
    registerModule<T extends typeof Module>(moduleClass: T): Container;
    /** Register named modules in container. */
    registerModules<T extends typeof Module>(modules: T[]): Container;
    /** Register a value of type in container. */
    registerValue<T>(name: string, value: T): Container;
    /** Resolve value or module of type from container by name. */
    resolve<T>(name: string): T;
    /** Send log message of level for module. */
    sendLog(level: ELogLevel, message: ILogMessage, metadata: ILogMetadata, args: any[]): void;
    /** Send metric message of type for module. */
    sendMetric(type: EMetricType, name: string, value: any, tags: IMetricTags, args: any[]): void;
    /** Observable stream of module logs filtered by level. */
    filterLogs(level: ELogLevel): Observable<ContainerLogMessage>;
    /** Observable stream of module metrics filtered by type. */
    filterMetrics(type: EMetricType): Observable<ContainerMetricMessage>;
    /**
     * Signal modules to enter operational state.
     * Module hook method `moduleUp` called in order of dependencies.
     */
    up(timeout?: number): Promise<number>;
    /**
     * Signal modules to leave operational state.
     * Module hook method `moduleDown` called in order of dependents.
     */
    down(timeout?: number): Promise<number>;
    /** Call modules destroy hooks before process exit. */
    destroy(): void;
    /** Wait for modules to enter operational state before calling next. */
    protected containerWhenModulesUp(...modules: string[]): Promise<void>;
    /** Wait for modules to leave operational state before calling next. */
    protected containerWhenModulesDown(...modules: string[]): Promise<void>;
    /** Create a new instance of module class. */
    protected containerModuleFactory<T extends typeof Module>(moduleClass: T, opts: any): Module;
    /** Returns list of module names which are dependencies of target module. */
    protected containerModuleDependencies(mod: Module): string[];
    /** Returns list of module names which are dependents of target module. */
    protected containerModuleDependents(mod: Module): string[];
    /** Returns true if module is already registered in container. */
    protected containerModuleRegistered(name: string): boolean;
    /** Wrap module hook promise with timeout operator, call containerModuleState on next. */
    protected containerModuleStateTimeout(hook: Promise<void>, moduleName: string, state: boolean, timeout?: number): Promise<void>;
    /** Update observable modules state for target module. */
    protected containerModuleState(name: string, state: boolean): void;
    /** Internal handler for `up` and `down` methods of class. */
    protected containerState(hooks: Promise<void>[], state: boolean): Promise<number>;
}
