import { ServiceConfig } from "./service-config";
import { ServiceDependent } from "./service-dependent";
import { ServiceExecution } from "./service-execution";
import { Class, ServiceIdentifier } from "./service-types";
export declare class Service extends ServiceDependent {
    /** Called once the service instance has been constructed. The passed `execution` will be set done once the service has no more dependents
     * and all of the defined `deconstructFns` have been called. */
    protected asyncConstructor?(execution: ServiceExecution): Promise<any> | void;
    /** Defined to return and specify the service configuration. It can also be defined using the `servido.confgure` utility,
     * but that obviously omits the possibility of specifying types for the service data. */
    protected getServiceConfig?(): ServiceConfig;
    constructor();
    /** Functions that should be called once there are no remaining dependents of the service and it is to be removed from memory. */
    protected get deconstructFns(): Set<Function>;
    protected toString(): string;
    /** Generate a `ServiceIdentifier` for a set of passed arguments. A prototype extending `Service` can override the method. */
    static identifier(...args: any[]): ServiceIdentifier;
    /** Resolve the promise returned by the `asyncConstructor` method of every passed `Service`. */
    static resolve<S extends (Service | undefined)[]>(...services: S): Promise<S>;
    /** The amount of time in ms to wait until finally deconstructing the service. Defaults to `1`, meaning a synchronous switch of dependents will not
     * deconstruct the service, which would not have been the case if it was `0`. */
    static deconstructTimeout: number;
    /** The key for the data. */
    static get key(): string;
    /** The key for the data. */
    static set key(key: string);
}
/** A utility for defining a set of service depencencies, which is useful for knowing when a part of an app is loaded. */
export declare class ServiceDependency extends Service {
    private dependencies;
    constructor(dependencies?: ServiceClass<Service, []>[]);
    /** Add a dependency to be included in this dependency. */
    protected add(dependency: ServiceClass<Service, []>): void;
    protected add<A extends any[]>(dependency: ServiceClass<Service, A>, ...args: A): void;
    protected add(dependency: Service): void;
    protected asyncConstructor(): Promise<void>;
    static from(dependencies: ServiceClass<Service, []>[]): Class<ServiceDependency, []>;
    static from(dependencies: ServiceClass<Service, []>[], require: (require: Service["require"]) => void): Class<ServiceDependency, []>;
    static from(require: (require: Service["require"]) => void): Class<ServiceDependency, []>;
}
export interface ServiceClass<S extends Service = Service, A extends any[] = any[]> extends Class<S, A> {
    /** Generate a `ServiceIdentifier` for a set of passed arguments */
    identifier?(...args: A): ServiceIdentifier;
    /** The amount of time in ms to wait until finally deconstructing the service. Defaults to `1`, meaning a synchronous switch of dependents will not
     * deconstruct the service, which would not have been the case if it was `0`. */
    deconstructTimeout?: number;
    /** The key for the data. */
    key?: string;
}
export declare type ServiceQuery<S extends Service, A extends any[] = any[], QA extends any[] = any[]> = S | Class<S, A> | ServiceSource<S, A> | [service: ServiceType<S, QA>, ...arguments: QA] | [service: Class<S, QA>, ...arguments: QA] | [service: ServiceSource<S, QA>, ...arguments: QA];
export declare type ServiceType<S extends Service, A extends any[] = any[]> = Class<S, A> | ServiceSource<S, A>;
export interface ServiceThunk<S extends Service, A extends any[] = any[]> {
    (...args: A): ServiceQuery<S, A>;
}
export interface ServiceSource<S extends Service = Service, A extends any[] = any[]> {
    getService?(...args: A): ServiceQuery<S, A>;
    service?: ServiceQuery<S, A>;
}
