import { FDisposable, FExecutionContext, type FChannelPublisher, type FChannelSubscriber, FCancellationToken, FInitableBase, FLogger } from "@freemework/common";
import express from 'express';
import http from "http";
import https from "https";
import WebSocket from "ws";
import { FHostingSettings } from "./f_hosting_settings.js";
export { FHostingSettings, FHostingConfiguration } from "./f_hosting_settings.js";
export { FHttpRequestCancellationToken } from "./FHttpRequestCancellationToken.js";
export * from "./configuration/index.js";
export * from "./launcher/index.js";
export type FWebServerRequestHandler = http.RequestListener;
export interface FWebServer extends FInitableBase {
    readonly name: string;
    readonly underlyingServer: http.Server | https.Server;
    rootExpressApplication: express.Application;
    bindRequestHandler(bindPath: string, handler: FWebServerRequestHandler): void;
    createWebSocketServer(bindPath: string): WebSocket.Server;
    destroyWebSocketServer(bindPath: string): Promise<void>;
}
export declare abstract class FAbstractWebServer<TOpts extends FHostingSettings.WebServerBase | FHostingSettings.WebServer> extends FInitableBase implements FWebServer {
    abstract readonly underlyingServer: http.Server | https.Server;
    protected readonly _trustProxy: boolean | "loopback" | "linklocal" | "uniquelocal";
    protected readonly _name: string;
    protected readonly _listenHost: string;
    protected readonly _listenPort: number;
    protected readonly _webSockets: {
        [bindPath: string]: WebSocket.Server;
    };
    protected readonly _log: FLogger;
    protected readonly _handleUpgrade: boolean;
    private readonly _onUpgrade;
    private readonly _onRequestImpl;
    private readonly _handlers;
    private _rootExpressApplication;
    static createFCancellationToken(request: http.IncomingMessage): FCancellationToken;
    constructor(opts: TOpts);
    /**
     * Lazy create for Express Application
     */
    get rootExpressApplication(): express.Application;
    set rootExpressApplication(value: express.Application);
    get name(): string;
    bindRequestHandler(bindPath: string, value: FWebServerRequestHandler): void;
    createWebSocketServer(bindPath: string): WebSocket.Server;
    destroyWebSocketServer(bindPath: string): Promise<void>;
    protected onInit(): Promise<void>;
    protected abstract onListen(): Promise<void>;
    protected onRequest(req: http.IncomingMessage, res: http.ServerResponse): void;
    private onRequestCommon;
    private onRequestXFCC;
    private onUpgradeCommon;
    private onUpgradeXFCC;
    private validateXFCC;
}
export declare class UnsecuredWebServer extends FAbstractWebServer<FHostingSettings.UnsecuredWebServer> {
    private readonly _httpServer;
    constructor(opts: FHostingSettings.UnsecuredWebServer);
    get underlyingServer(): http.Server;
    protected onListen(): Promise<void>;
    protected onDispose(): Promise<void>;
}
export declare class SecuredWebServer extends FAbstractWebServer<FHostingSettings.SecuredWebServer> {
    private readonly _httpsServer;
    constructor(opts: FHostingSettings.SecuredWebServer);
    get underlyingServer(): https.Server;
    protected onListen(): Promise<void>;
    protected onDispose(): Promise<void>;
}
export declare abstract class FBindEndpoint extends FInitableBase {
    protected readonly _bindPath: string;
    constructor(opts: FHostingSettings.BindEndpoint);
    protected onInit(): void | Promise<void>;
    protected onDispose(): void | Promise<void>;
}
export declare abstract class FServersBindEndpoint extends FBindEndpoint {
    protected readonly _servers: ReadonlyArray<FWebServer>;
    constructor(servers: ReadonlyArray<FWebServer>, opts: FHostingSettings.BindEndpoint);
}
/**
 * This endpoint supplies communication channels for each client connection.
 *
 * WebSocket Client is hosting the channel:
 *   - Client's messages delivered via SubscriberChannel
 *   - To deliver message to client use PublisherChannel
 *
 * If you need opposite behavior take a look for `WebSocketChannelFactoryEndpoint`
 *
 * You need to override onOpenBinaryChannel and/or onOpenTextChannel to obtain necessary channel
 */
export declare class FWebSocketChannelSupplyEndpoint extends FServersBindEndpoint {
    private readonly _webSocketServers;
    private readonly _connections;
    private readonly _log;
    private _defaultProtocol;
    private _allowedProtocols;
    private _connectionCounter;
    constructor(servers: ReadonlyArray<FWebServer>, opts: FHostingSettings.WebSocketEndpoint);
    protected onInit(): void;
    protected onDispose(): Promise<void>;
    protected onConnection(webSocket: WebSocket, request: http.IncomingMessage): void;
    /**
     * The method should be overridden. The method called by the endpoint,
     * when WSClient sent first binary message for specified sub-protocol.
     * @param webSocket WebSocket instance
     * @param subProtocol These strings are used to indicate sub-protocols,
     * so that a single server can implement multiple WebSocket sub-protocols (for example,
     * you might want one server to be able to handle different types of interactions
     * depending on the specified protocol).
     * @param channel Binary channel instance to be user in inherited class
     */
    protected onOpenBinaryChannel(_webSocket: WebSocket, subProtocol: string, _channel: FWebSocketChannelSupplyEndpoint.BinaryChannel): void;
    /**
     * The method should be overridden. The method called by the endpoint,
     * when WSClient sent first text message for specified sub-protocol.
     * @param webSocket WebSocket instance
     * @param subProtocol These strings are used to indicate sub-protocols,
     * so that a single server can implement multiple WebSocket sub-protocols (for example,
     * you might want one server to be able to handle different types of interactions
     * depending on the specified protocol).
     * @param channel Text channel instance to be user in inherited class
     */
    protected onOpenTextChannel(_webSocket: WebSocket, subProtocol: string, _channel: FWebSocketChannelSupplyEndpoint.TextChannel): void;
}
export declare namespace FWebSocketChannelSupplyEndpoint {
    interface BinaryChannel extends FChannelPublisher<Uint8Array>, FChannelSubscriber<Uint8Array> {
    }
    interface TextChannel extends FChannelPublisher<string>, FChannelSubscriber<string> {
    }
}
/**
 * This endpoint requests you for communication channels for each client connection.
 *
 * WebSocket Client is used the channel:
 *   - Client's messages delivered via PublisherChannel
 *   - To deliver message to client use SubscriberChannel
 *
 * If you need opposite behavior take a look for `WebSocketChannelSupplyEndpoint`
 *
 * You need to override createBinaryChannel and/or createTextChannel to provide necessary channel
 */
export declare class FWebSocketChannelFactoryEndpoint extends FServersBindEndpoint {
    private readonly _webSocketServers;
    private readonly _connections;
    private readonly _autoCreateChannelBinary;
    private readonly _autoCreateChannelText;
    private readonly _log;
    private _defaultProtocol;
    private _allowedProtocols;
    private _connectionCounter;
    constructor(servers: ReadonlyArray<FWebServer>, opts: FHostingSettings.WebSocketEndpoint, autoCreateChannels?: {
        binary?: boolean;
        text?: boolean;
    });
    protected onInit(): void;
    protected onDispose(): Promise<void>;
    protected onConnection(webSocket: WebSocket, request: http.IncomingMessage): Promise<void>;
    /**
     * The method should be overridden. The method called by the endpoint,
     * when WSClient sent first binary message for specified sub-protocol.
     * @param webSocket WebSocket instance
     * @param subProtocol These strings are used to indicate sub-protocols,
     * so that a single server can implement multiple WebSocket sub-protocols (for example,
     * you might want one server to be able to handle different types of interactions
     * depending on the specified protocol).
     */
    protected createBinaryChannel(_executionContext: FExecutionContext, _webSocket: WebSocket, subProtocol: string): Promise<FWebSocketChannelFactoryEndpoint.BinaryChannel>;
    /**
     * The method should be overridden. The method called by the endpoint,
     * when WSClient sent first text message for specified sub-protocol.
     * @param webSocket WebSocket instance
     * @param subProtocol These strings are used to indicate sub-protocols,
     * so that a single server can implement multiple WebSocket sub-protocols (for example,
     * you might want one server to be able to handle different types of interactions
     * depending on the specified protocol).
     */
    protected createTextChannel(_executionContext: FExecutionContext, _webSocket: WebSocket, subProtocol: string): Promise<FWebSocketChannelFactoryEndpoint.TextChannel>;
}
export declare namespace FWebSocketChannelFactoryEndpoint {
    interface BinaryChannel extends FDisposable, FChannelPublisher<Uint8Array>, FChannelSubscriber<Uint8Array> {
    }
    interface TextChannel extends FDisposable, FChannelPublisher<string>, FChannelSubscriber<string> {
    }
}
export declare function instanceofWebServer(server: any): server is FWebServer;
export declare function createWebServer(serverOpts: FHostingSettings.WebServer): FWebServer;
export declare function createWebServers(serversOpts: ReadonlyArray<FHostingSettings.WebServer>): ReadonlyArray<FWebServer>;
