/**
 * @module Utilities
 */
import { type IInvokableObject, type Invokable, type InvokableFn, type OneOrMore } from "../../../utilities/functions/_module.js";
import type { HookContext } from "../../../utilities/classes/hooks/types.js";
/**
 *
 * IMPORT_PATH: `"@daiso-tech/core/utilities"`
 * @group Hooks
 */
export type NextFunc<TParameters extends unknown[] = unknown[], TReturn = unknown> = InvokableFn<TParameters, TReturn>;
/**
 *
 * IMPORT_PATH: `"@daiso-tech/core/utilities"`
 * @group Hooks
 */
export type Context<TContext extends HookContext = HookContext> = {
    name: string;
    context: TContext;
};
/**
 *
 * IMPORT_PATH: `"@daiso-tech/core/utilities"`
 * @group Hooks
 */
export type MiddlewareFn<TParameters extends unknown[] = unknown[], TReturn = unknown, TContext extends HookContext = HookContext> = InvokableFn<[
    arguments_: TParameters,
    next: NextFunc<TParameters, TReturn>,
    settings: Context<TContext>
], TReturn>;
/**
 *
 * IMPORT_PATH: `"@daiso-tech/core/utilities"`
 * @group Hooks
 */
export type IMiddlewareObject<TParameters extends unknown[] = unknown[], TReturn = unknown, TContext extends HookContext = HookContext> = IInvokableObject<[
    arguments_: TParameters,
    next: NextFunc<TParameters, TReturn>,
    settings: Context<TContext>
], TReturn>;
/**
 *
 * IMPORT_PATH: `"@daiso-tech/core/utilities"`
 * @group Hooks
 */
export type Middleware<TParameters extends unknown[] = unknown[], TReturn = unknown, TContext extends HookContext = HookContext> = IMiddlewareObject<TParameters, TReturn, TContext> | MiddlewareFn<TParameters, TReturn, TContext>;
/**
 *
 * IMPORT_PATH: `"@daiso-tech/core/utilities"`
 * @group Hooks
 */
export type HooksSettings<TContext extends HookContext = HookContext> = {
    /**
     * The name of the function which can be used for logging inside the middleware.
     * By default, it takes the function or method name. If an anonymous function is provided, the name defaults to "func".
     */
    name?: string;
    /**
     * You can provide addtional context that can be used in the middleware.
     */
    context?: TContext;
};
/**
 * The `Hooks` class provides a convenient way to change and inspect arguments and return value of only sync functions.
 * For example `Hooks` class can be used to log function arguments and return values. Note this class is immutable.
 *
 * Middlewares apply left to right: each wraps the next, with the leftmost being the outermost layer and the rightmost wrapping the original function.
 *
 * IMPORT_PATH: `"@daiso-tech/core/utilities"`
 * @group Hooks
 */
export declare class Hooks<TParameters extends unknown[] = unknown[], TReturn = unknown, TContext extends HookContext = HookContext> implements IInvokableObject<TParameters, TReturn> {
    private readonly invokable;
    private readonly middlewares;
    private readonly settings;
    private static init;
    private readonly func;
    /**
     * @example
     * ```ts
     * import { Hooks, type MiddlewareFn } from "@daiso-tech/core/utilities";
     *
     * function log<TParameters extends unknown[], TReturn>(): MiddlewareFn<TParameters, TReturn, { funcName: string; }> {
     *   return (args, next, { name: funcName }) => {
     *     console.log("FUNCTION_NAME:", funcName);
     *     console.log("ARGUMENTS:", args);
     *     const value = next(...args);
     *     console.log("RETURN:", value);
     *     return value;
     *   }
     * }
     *
     * function time<TParameters extends unknown[], TReturn>(): MiddlewareFn<TParameters, TReturn> {
     *   return (args, next) => {
     *     const start = performance.now();
     *     const value = next(...args);
     *     const end = performance.now();
     *     const time = end - start;
     *     console.log("TIME:", `${String(time)}ms`);
     *     return value;
     *   }
     * }
     *
     * function add(a: number, b: number): number {
     *   return a + b;
     * }
     *
     * const enhancedAdd = new Hooks(add, [
     *   log(),
     *   time()
     * ], {
     *   // You can provide addtional data to be used the middleware.
     *   context: {},
     * });
     *
     * // Will log the function name, arguments and return value.
     * // Will also log the execution time.
     * const result = enhancedAdd.invoke(1, 2);
     *
     * // Will be 3.
     * console.log(result);
     * ```
     */
    constructor(invokable: Invokable<TParameters, TReturn>, middlewares: NoInfer<OneOrMore<Middleware<TParameters, TReturn, TContext>>>, settings?: HooksSettings<TContext>);
    /**
     * The `pipe` method returns a new `Hooks` instance with the additional `middlewares` applied.
     */
    pipe(middlewares: OneOrMore<Middleware<TParameters, TReturn, TContext>>): Hooks<TParameters, TReturn, TContext>;
    /**
     * The `pipeWhen` method conditionally applies additional `middlewares`, returning a new `Hooks` instance only if the specified condition is met.
     */
    pipeWhen(condition: boolean, middlewares: OneOrMore<Middleware<TParameters, TReturn, TContext>>): Hooks<TParameters, TReturn, TContext>;
    /**
     * The `toFunc` will return the function with all middlewares applied.
     */
    toFunc(): InvokableFn<TParameters, TReturn>;
    /**
     * The `invoke` method executes the constructor's input function, applying all middlewares.
     */
    invoke(...arguments_: TParameters): TReturn;
}
