type RuntimeConfiguration = {
    source: string;
    target: string;
    segments: string;
    resources: string;
    build: {
        ignore: string[];
    };
    meta: {
        root: string;
        configFile: string;
    };
};

type GatewayConfiguration = {
    monitorInterval?: number;
    trustKey?: string;
};

type ProxyConfiguration = {
    gateway: string;
    repository: string;
};

type RepositoryConfiguration = {
    indexFilename?: string;
    serveIndexOnNotFound?: boolean;
    assetRoot?: string;
    assets?: string[];
};

type WorkerConfiguration = {
    gateway?: string;
    segments: string[];
    trustKey?: string;
    reportInterval?: number;
};

type StandaloneConfiguration = RepositoryConfiguration & Pick<WorkerConfiguration, 'segments'>;

type RemoteWorkerConfiguration = {
    unavailableThreshold?: number;
    stoppedThreshold?: number;
};

type ServerConfiguration = {
    url: string;
    setUp?: string[];
    tearDown?: string[];
    middleware?: string[];
    healthChecks?: string[];
    gateway?: GatewayConfiguration;
    proxy?: ProxyConfiguration;
    repository?: RepositoryConfiguration;
    standalone?: StandaloneConfiguration;
    worker?: WorkerConfiguration;
    remoteWorker?: RemoteWorkerConfiguration;
    meta: {
        root: string;
        configFile: string;
    };
};

declare class ConfigurationManager {
    #private;
    constructor(rootPath?: string);
    configureEnvironment(filename?: string): Promise<void>;
    getRuntimeConfiguration(filename?: string): Promise<RuntimeConfiguration>;
    getServerConfiguration(filename: string): Promise<ServerConfiguration>;
}

declare class BuildHelper {
    #private;
    constructor(configuration: RuntimeConfiguration);
    readApplication(): Promise<void>;
    generateModuleCode(filename: string, segmentNames?: string[]): string;
}

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>;
}

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