/// <reference types="node" />
import ws, { ServerOptions } from 'ws';
import { Server, IncomingMessage } from 'http';

type DataType = Record<string, any>;
type ClientSocket = ws & {
    userData: DataType;
};
type MessageObject$1 = {
    path: string;
    data: DataType;
    requestId?: string;
};
type sendMessageToAllOptions = {
    exceptions: ClientSocket[] | string[];
};
type onConnection = (socket: ClientSocket, req: IncomingMessage) => Promise<void> | void;
type onAuth = (socket: ClientSocket, message: Buffer) => Promise<void> | void;
type onAuthSuccess = (socket: ClientSocket, message: Buffer) => Promise<void> | void;
type onAuthFailure = (socket: ClientSocket, error: Error, message: Buffer) => Promise<void> | void;
type onMessage = (socket: ClientSocket, messageObject: MessageObject$1) => Promise<void> | void;
type onClose$1 = (socket: ClientSocket) => Promise<void> | void;
type onError = (socket: ClientSocket, err: Error) => Promise<void> | void;
type SocketOptions = {
    serverOptions?: ServerOptions;
    actionsPath?: string;
    actions?: Record<string, Action>;
    disableAuthentication?: boolean;
    onConnection?: onConnection;
    onAuth?: onAuth;
    onAuthSuccess?: onAuthSuccess;
    onAuthFailure?: onAuthFailure;
    onClose?: onClose$1;
    onError?: onError;
    onMessage?: onMessage;
};
declare class Socket {
    protected _server: Server | undefined;
    protected readonly onConnection: onConnection;
    protected readonly onAuth: onAuth;
    protected readonly onAuthSuccess: onAuthSuccess;
    protected readonly onAuthFailure: onAuthFailure;
    protected readonly onClose: onClose$1;
    protected readonly onError: onError;
    protected readonly onMessage: onMessage;
    protected readonly Actions: Record<string, Action>;
    protected readonly disableAuthentication: boolean;
    protected readonly _activeClients: ClientSocket[];
    private wsInstance;
    private readonly serverOptions;
    constructor(options: SocketOptions);
    initActions({ actions, actionsPath }: SocketOptions): Promise<void>;
    start(): Promise<void>;
    restart(): Promise<void>;
    protected prepareAllActions(): Promise<void>;
    protected connecting(socket: ClientSocket, req: IncomingMessage): Promise<void>;
    protected authenticating(socket: ClientSocket, message: Buffer): Promise<void>;
    protected receivingMessage(socket: ClientSocket, message: string): Promise<void>;
    protected reportingError(socket: ClientSocket, err: Error): Promise<void>;
    protected closing(socket: ClientSocket): Promise<void>;
    closeSocket(cb?: ((err?: Error | undefined) => void) | undefined): void;
    close(socketCallback?: ((err?: Error | undefined) => void) | undefined, expressCallback?: (err?: Error | undefined) => void): void;
    get activeClients(): DataType[];
    get server(): Server | undefined;
    sendMessage(socket: ClientSocket, data: DataType | string): void;
    sendMessageById(id: string, data: DataType | string): void;
    sendMessageToAll(data: DataType | string, { exceptions }: sendMessageToAllOptions): void;
}

type ActionParameters = {
    socket: ClientSocket;
    userData: DataType;
    requestId: string | undefined;
    data: DataType;
};
type OnRunParameters = {
    socket: ClientSocket;
    userData: DataType;
    data: DataType;
    respond: (data: DataType) => void;
};
declare abstract class Action {
    protected server: Socket | null;
    prepareAction(server: Socket): Promise<void>;
    protected onCheckPermissions(_parameters: ActionParameters): Promise<void> | void;
    protected onError(_parameters: ActionParameters, err: unknown): Promise<void> | void;
    run(parameters: ActionParameters): Promise<void>;
    abstract onRun(data: OnRunParameters): Promise<void> | void;
}

declare const _default$2: {
    default: typeof Socket;
    Action: typeof Action;
    Socket: typeof Socket;
};

type MessageObject = MessageEvent & {
    requestId?: string;
};
type onOpen = () => Promise<void> | void;
type onClose = () => Promise<void> | void;
type messageReceiver = (message: MessageObject) => Promise<void> | void;
type clientOptions = {
    url?: string;
    authentication?: any;
    connectionTryLimit?: number;
    secondsBetweenRetries?: number;
    protocols?: string | string[];
    onOpen?: onOpen;
    onClose?: onClose;
    onMessage?: messageReceiver;
    onAuthResponse?: messageReceiver;
    onAuthFailure?: messageReceiver;
};
declare class Client {
    private _authentication;
    private _socket;
    private readonly url;
    private readonly protocols;
    private readonly preparedOnAuthResponse;
    private readonly preparedOnMessageResponse;
    private readonly onMessage;
    private readonly onAuthResponse;
    private readonly onOpen;
    private readonly onClose;
    private readonly onAuthFailure;
    private connectionTries;
    private readonly connectionTryLimit;
    private readonly secondsBetweenRetries;
    private _isAuthenticated;
    private _isConnected;
    private requests;
    constructor(options?: clientOptions);
    private connect;
    reconnect(): void;
    private opening;
    private closing;
    close(code?: number | undefined, reason?: string | undefined): void;
    private enableMessageReceiver;
    private disableMessageReceiver;
    private authResponse;
    private messageResponse;
    get authentication(): any;
    get isAuthenticated(): boolean;
    get isConnected(): boolean;
    get socket(): WebSocket | null;
    tryAuth(authentication?: any): void;
    sendAction(path: string, data?: Record<string, any>, extraDetails?: Record<string, any>): void;
    sendRequest(path: string, data?: Record<string, any>, timeout?: number): Promise<Record<string, any>>;
}

type FactoryPromise = (...args: any[]) => Promise<void>;
type FactoryFunction = (...args: any[]) => void;

declare function sleep(miliseconds: number): Promise<unknown>;

declare const _default$1: {
    default(miliseconds: number): Promise<unknown>;
    ListenerFactory: (ctx: Socket | Client, socket: ClientSocket | null, callback: FactoryPromise) => FactoryFunction;
    ParseCookies: (cookieString: string) => any;
    Sleep: typeof sleep;
};

declare const _default: {
    Client: typeof Client;
    Helpers: {
        default(miliseconds: number): Promise<unknown>;
        ListenerFactory: (ctx: Socket | Client, socket: ClientSocket | null, callback: FactoryPromise) => FactoryFunction;
        ParseCookies: (cookieString: string) => any;
        Sleep: typeof sleep;
    };
    Server: {
        default: typeof Socket;
        Action: typeof Action;
        Socket: typeof Socket;
    };
};

export { Client, _default$1 as Helpers, _default$2 as Server, _default as default };
