import { WorkerLogLevel } from "@webda/workout";
import * as events from "events";
import { Constructor, Core, Counter, Gauge, Histogram, Logger, MetricConfiguration, OperationContext } from "../index.js";
import { OpenAPIWebdaDefinition } from "../router.js";
import { HttpMethodType } from "../utils/httpcontext.js";
/**
 * Inject a Bean inside this attribute
 *
 * If defaultValue is undefined and parameter is not starting with `params:`, it will
 * resolve by calling `this.getService(parameterOrName)`
 *
 * If defaultValue is defined or parameterOrName starts with `params:` then first argument is
 * consider a parameter and it will resolve by calling `this.getService(this.getParameters()[parameterOrName] || defaultValue)`
 *
 * @param parameterOrName of the service to inject
 *
 * Might consider to split into two annotations
 */
export declare function Inject(parameterOrName?: string, defaultValue?: string | boolean, optional?: boolean): (target: any, propertyName: string) => void;
/**
 * Register an Operation within the framework
 *
 * An operation is a callable method with an input and output
 * The method will receive a Context from where it can execute
 *
 * @param id
 * @param input
 * @param output
 */
export declare function Operation(properties?: {
    /**
     * Id of the Operation
     *
     * @default methodName
     */
    id?: string;
    /**
     * WebdaQL to execute on session object to ensure it can access
     */
    permission?: string;
}, route?: {
    url: string;
    method?: HttpMethodType;
    openapi?: OpenAPIWebdaDefinition;
}): (target: any, executor: string) => void;
export declare function Route(route: string, methods?: HttpMethodType | HttpMethodType[], openapi?: OpenAPIWebdaDefinition): (target: any, executor: string) => void;
/**
 * A utility class that takes a array of string or string transformed into regex that includes
 * a start line and end line
 */
export declare class RegExpValidator {
    protected validators: RegExp[];
    constructor(info: string | string[]);
    static getRegExp(reg: string): RegExp;
    validate(value: string): boolean;
}
/**
 * Standardized way to allow string/regex validation within configuration
 *
 * If url is prefixed with `regex:` it is considered a regex
 *
 * @example
 * ```typescript
 * class MyServiceParameters extends ServiceParameters {
 *    urls: string[];
 * }
 *
 * class MyService extends Service {
 *    loadParameters(params:any) {
 *      const parameters = new MyServiceParameters(params);
 *      this.urlsValidator = new RegExpStringValidator(parameters.urls);
 *      return parameters;
 *    }
 * }
 * ```
 */
export declare class RegExpStringValidator extends RegExpValidator {
    stringValidators: string[];
    constructor(info: string | string[]);
    /**
     * Add string validation
     * @param value
     * @returns
     */
    validate(value: string): boolean;
}
/**
 * Interface to specify the Service parameters
 */
export declare class ServiceParameters {
    /**
     * Type of the service
     */
    type: string;
    /**
     * URL on which to serve the content
     */
    url?: string;
    /**
     * OpenAPI override
     * @SchemaIgnore
     */
    openapi?: OpenAPIWebdaDefinition;
    /**
     * Copy all parameters into the object by default
     *
     * @param params from webda.config.json
     */
    constructor(params: any);
}
/**
 * Create a new type with only optional
 */
export type DeepPartial<T> = {
    [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
export type PartialModel<T> = {
    [P in keyof T]: T[P] extends Function ? T[P] : T[P] extends object ? null | PartialModel<T[P]> : T[P] | null;
};
export type Events = {
    [key: string]: unknown;
};
/**
 * Use this object for representing a service in the application
 * A Service is a singleton in the application, that is init after all others services are created
 *
 * You can use a Service to create Listeners or implement shared behavior between others services
 *
 * @exports
 * @abstract
 * @class Service
 */
declare abstract class Service<T extends ServiceParameters = ServiceParameters, E extends Events = Events> extends events.EventEmitter {
    /**
     * Webda Core object
     */
    protected _webda: Core;
    /**
     * Service name
     */
    protected _name: string;
    /**
     * Hold the parameters for your service
     *
     * It will be bring from the `webda.config.json`
     */
    protected parameters: T;
    _createException: string;
    _initTime: number;
    _initException: any;
    /**
     * Logger with class context
     */
    protected logger: Logger;
    /**
     * Get metrics
     */
    protected metrics?: any;
    /**
     *
     *
     * @class Service
     * @param {Webda} webda - The main instance of Webda
     * @param {String} name - The name of the service
     * @param {Object} params - The parameters block define in the configuration file
     */
    constructor(webda: Core, name: string, params?: DeepPartial<T>);
    /**
     * Load the parameters for a service
     */
    loadParameters(params: DeepPartial<T>): ServiceParameters;
    /**
     * Used to compute or derivate input parameter to attribute
     */
    computeParameters(): void;
    /**
     * Get the service parameters
     */
    getParameters(): T;
    /**
     * Return WebdaCore
     */
    getWebda(): Core;
    /**
     * Shutdown the current service if action need to be taken
     */
    stop(): Promise<void>;
    /**
     * Return service representation
     */
    toString(): string;
    /**
     * Resolve parameters
     * Call initRoutes and initBeanRoutes
     */
    resolve(): this;
    /**
     * Init the metrics
     */
    initMetrics(): void;
    /**
     * Add service name label
     * @param type
     * @param configuration
     * @returns
     */
    getMetric<T = Gauge | Counter | Histogram>(type: Constructor<T, [MetricConfiguration<T>]>, configuration: MetricConfiguration<T>): T;
    /**
     * Return the events that an external system can subscribe to
     *
     * @returns
     */
    getClientEvents(): string[];
    /**
     * Authorize a public event subscription
     * @param event
     * @param context
     */
    authorizeClientEvent(_event: string, _context: OperationContext): boolean;
    /**
     * Return the full path url based on parameters
     *
     * @param url relative url to service
     * @param _methods in case we need filtering (like Store)
     * @returns absolute url or undefined if need to skip the Route
     */
    getUrl(url: string, _methods: HttpMethodType[]): string;
    /**
     * If undefined is returned it cancel the operation registration
     * @param id
     * @returns
     */
    getOperationId(id: string): string | undefined;
    /**
     * Add a route dynamicaly
     *
     * @param {String} url of the route can contains dynamic part like {uuid}
     * @param {Array[]} methods
     * @param {Function} executer Method to execute for this route
     */
    protected addRoute(url: string, methods: HttpMethodType[], executer: Function, openapi?: OpenAPIWebdaDefinition, override?: boolean): void;
    /**
     * Return variables for replacement in openapi
     * @returns
     */
    getOpenApiReplacements(): any;
    /**
     * Init the routes
     */
    initRoutes(): void;
    /**
     * Init the operations
     */
    initOperations(): void;
    /**
     * Convert an object to JSON using the Webda json filter
     *
     * @class Service
     * @param {Object} object - The object to export
     * @return {String} The export of the strip object ( removed all attribute with _ )
     */
    toPublicJSON(object: unknown): string;
    /**
     * Prevent service to be serialized
     * @returns
     */
    toJSON(): string;
    /**
     * Will be called after all the Services are created
     *
     * @param config for the host so you can add your own route here
     * @abstract
     */
    init(): Promise<this>;
    /**
     *
     * @param config new parameters for the service
     */
    reinit(config: DeepPartial<T>): Promise<this>;
    /**
     * Emit the event with data and wait for Promise to finish if listener returned a Promise
     */
    emitSync<Key extends keyof E>(event: Key, data: E[Key]): Promise<any[]>;
    /**
     * Override to allow capturing long listeners
     * @override
     */
    emit<Key extends keyof E>(event: Key | symbol, data: E[Key]): boolean;
    /**
     * Type the listener part
     * @param event
     * @param listener
     * @param queue
     * @returns
     */
    on<Key extends keyof E>(event: Key | symbol, listener: (evt: E[Key]) => void): this;
    /**
     * Listen to an event as on(...) would do except that it will be asynchronous
     * @param event
     * @param callback
     * @param queue Name of queue to use, can be undefined, queue name are used to define differents priorities
     */
    onAsync<Key extends keyof E>(event: Key, listener: (evt: E[Key]) => void, queue?: string): void;
    /**
     * Return a webda service
     * @param service name to retrieve
     */
    getService<K extends Service<ServiceParameters>>(service: string): K;
    /**
     * Get service name
     */
    getName(): string;
    /**
     * Clean the service data, can only be used in test mode
     *
     * @abstract
     */
    __clean(): Promise<void>;
    /**
     * @private
     */
    ___cleanData(): Promise<void>;
    /**
     *
     * @param level to log
     * @param args
     */
    log(level: WorkerLogLevel, ...args: any[]): void;
}
export { Service };
