declare class BadRequest extends Error {
    constructor(message?: string);
}

declare class Forbidden extends Error {
    constructor(message?: string);
}

declare class NotFound extends Error {
    constructor(message?: string);
}

declare class NotImplemented extends Error {
    constructor(message?: string);
}

declare class PaymentRequired extends Error {
    constructor(message?: string);
}

declare class ServerError extends Error {
    constructor(message?: string);
}

declare class Teapot extends Error {
    constructor(message?: string);
}

declare class Unauthorized extends Error {
    constructor(message?: string);
}

declare const AccessLevels: {
    readonly PRIVATE: "private";
    readonly PROTECTED: "protected";
    readonly PUBLIC: "public";
};
type Keys = keyof typeof AccessLevels;
type AccessLevel = typeof AccessLevels[Keys];

declare const RunModes: {
    readonly NORMAL: "normal";
    readonly DRY: "dry";
};
type RunMode = typeof RunModes[keyof typeof RunModes];

declare class Version {
    #private;
    static get DEFAULT(): Version;
    constructor(major?: number, minor?: number, patch?: number);
    get major(): number;
    get minor(): number;
    get patch(): number;
    equals(version: Version): boolean;
    greater(version: Version): boolean;
    less(version: Version): boolean;
    toString(): string;
}

declare class Request {
    #private;
    constructor(fqn: string, version: Version, args: Map<string, unknown>, headers: Map<string, string>, mode: RunMode);
    get fqn(): string;
    get version(): Version;
    get args(): Map<string, unknown>;
    get headers(): Map<string, string>;
    get mode(): RunMode;
    clearArguments(): void;
    setArgument(name: string, value: unknown): void;
    getArgument(name: string): unknown;
    hasArgument(name: string): boolean;
    removeArgument(name: string): void;
    clearHeaders(): void;
    setHeader(name: string, value: string): void;
    getHeader(name: string): string | undefined;
    hasHeader(name: string): boolean;
    removeHeader(name: string): void;
}

declare class Response {
    #private;
    constructor(status: number, result?: unknown, headers?: Map<any, any>);
    get status(): number;
    get result(): unknown;
    set result(value: unknown);
    get headers(): Map<string, string>;
    clearHeaders(): void;
    setHeader(name: string, value: string): void;
    getHeader(name: string): string | undefined;
    hasHeader(name: string): boolean;
    removeHeader(name: string): void;
}

declare class Class {
    #private;
    constructor(fqn: string, implementation: Function);
    get fqn(): string;
    get implementation(): Function;
}

declare class Parameter {
    #private;
    constructor(name: string, isOptional?: boolean);
    get name(): string;
    get isOptional(): boolean;
}

declare class Implementation {
    #private;
    constructor(version: Version, access: AccessLevel, parameters: Parameter[], executable: Function);
    get version(): Version;
    get public(): boolean;
    get protected(): boolean;
    get private(): boolean;
    get parameters(): Parameter[];
    get executable(): Function;
}

declare class Procedure {
    #private;
    constructor(fqn: string);
    get fqn(): string;
    get public(): boolean;
    get protected(): boolean;
    addImplementation(implementation: Implementation): this;
    getImplementation(version: Version): Implementation | undefined;
}

declare class Segment {
    #private;
    constructor(id: string);
    get id(): string;
    addClass(clazz: Class): this;
    hasClass(fqn: string): boolean;
    getClass(fqn: string): Class | undefined;
    getClassByImplementation(implementation: Function): Class | undefined;
    getClasses(): Class[];
    addProcedure(procedure: Procedure): this;
    hasProcedure(fqn: string): boolean;
    getProcedure(fqn: string): Procedure | undefined;
    getExposedProcedures(): Procedure[];
}

declare class NamedParameter extends Parameter {
}

declare class DestructuredParameter extends Parameter {
    #private;
    constructor(variables: Parameter[], name?: string, isOptional?: boolean);
    get variables(): Parameter[];
}

declare class ArrayParameter extends DestructuredParameter {
}

declare class ObjectParameter extends DestructuredParameter {
}

type NextHandler = () => Promise<Response>;

interface Middleware {
    handle(request: Request, next: NextHandler): Promise<Response>;
}

interface HealthCheck {
    get name(): string;
    get timeout(): number | undefined;
    isHealthy(): Promise<boolean>;
}

declare class CorsMiddleware implements Middleware {
    #private;
    constructor(origin?: string, headers?: string);
    get allowOrigin(): string;
    get allowMethods(): string;
    get allowHeaders(): string;
    handle(request: Request, next: NextHandler): Promise<Response>;
}

export { ArrayParameter, BadRequest, Class, CorsMiddleware, Forbidden, Implementation, NamedParameter, NotFound, NotImplemented, ObjectParameter, PaymentRequired, Procedure, Request, Response, Segment, ServerError, Teapot, Unauthorized, Version };
export type { HealthCheck, Middleware, NextHandler };
