import * as _qsocket_protocol from '@qsocket/protocol';
import { TQSocketProtocolPayloadData, IQSocketProtocolMessage, IQSocketProtocolPayload, IQSocketProtocolMessageMetaData, IQSocketProtocolMessageMetaAck, IQSocketProtocolMessageMetaControl, IQSocketProtocolChunk } from '@qsocket/protocol';

declare enum EQSocketListenerType {
    ON = 0,
    ONCE = 1
}
type TQSocketContentType = 'undefined' | 'null' | 'boolean' | 'number' | 'string' | 'json' | 'buffer';
type TListennerReturn<T extends TQSocketProtocolPayloadData> = Promise<T> | T;
type TQSocketListenerCallback<I extends TQSocketProtocolPayloadData, O extends TQSocketProtocolPayloadData> = (payload: I, contentType?: TQSocketContentType) => TListennerReturn<O>;
interface IQSocketListener<I extends TQSocketProtocolPayloadData, O extends TQSocketProtocolPayloadData> {
    /** Тип слушателя (ON/ONCE) */
    type: EQSocketListenerType;
    /** Слушатель */
    listener: TQSocketListenerCallback<I, O>;
    /** Тип контента по умолчанию */
    contentType?: TQSocketContentType;
}

interface IQSocketLogger {
    log(...message: any[]): void;
    error(...message: any[]): void;
    info(...message: any[]): void;
    debug(...message: any[]): void;
    warn(...message: any[]): void;
}
interface IQSocketConfigBase {
    /**  */
    timeout?: {
        value?: number;
        actionAfrer?: 'none' | 'resend';
    };
    debug?: {
        /** Включить отладку */
        enabled: boolean;
        /** Инстанс логгера */
        logger?: IQSocketLogger;
        /** Префикс перед всеми записями */
        prefix?: string;
    };
    /**
     * Выходной формат данных. (binary, base64)
     */
    format?: 'base64' | 'binary';
}
interface IQSocketClientConfig extends IQSocketConfigBase {
    /** Конфигурация переподключения */
    reconnection?: {
        enabled: boolean;
        maxAttempts?: number;
        delay?: number;
        exponentialBackoff?: boolean;
    };
}
interface IQSocketServerConfig extends IQSocketConfigBase {
}

declare class QSocketDebuger {
    /** Включен ли режим отладки */
    private readonly enabled;
    /** Префикс для сообщений логирования */
    private readonly prefix;
    /** Логгер, используемый для вывода сообщений */
    private readonly logger;
    /**
     * Конструктор класса QSocketUtils.
     * @param {IQSocketConfigBase['debug']} [debugConfig] - Конфигурация для режима отладки.
     */
    constructor(debugConfig?: IQSocketConfigBase['debug']);
    /**
     * Получает цветной префикс в зависимости от типа сообщения.
     * @param {string} type - Тип сообщения (log, error, info, warn).
     * @returns {string} - Цветной префикс.
     */
    private getColoredPrefix;
    /**
     * Логирует сообщение, если включен режим отладки.
     * @param {...any[]} message - Сообщение или данные для логирования.
     */
    log(...message: any[]): void;
    /**
     * Логирует сообщение об ошибке, если включен режим отладки.
     * @param {...any[]} message - Сообщение или данные для логирования ошибок.
     */
    error(...message: any[]): void;
    /**
     * Логирует информационное сообщение, если включен режим отладки.
     * @param {...any[]} message - Сообщение или данные для информационного логирования.
     */
    info(...message: any[]): void;
    /**
     * Логирует предупреждение, если включен режим отладки.
     * @param {...any[]} message - Сообщение или данные для логирования предупреждений.
     */
    warn(...message: any[]): void;
}

type TQSocketServer = any;
type TQSocketClientSocket = any;
type TQSocketServerSocket = any;
type TQSocketInteractionInstance = any;

/**
 * Класс для генерации уникальных идентификаторов (UUID), с возможностью добавления префикса.
 */
declare class QSocketUniqueGenerator<T extends string = ''> {
    /**
     * Текущий индекс для генерации UUID.
     * @private
     */
    private uuidIndex;
    private prefix;
    constructor(prefix?: T);
    /**
     * Метод для генерации следующего уникального идентификатора.
     */
    next(): `${T}${string}`;
}

type TMakeRequired<T> = {
    [K in keyof T]-?: T[K];
};

/** Выходной/входной формат сообщений */
declare const enum EDataFormat {
    Binary = 0,
    Base64 = 1
}

declare class QSocketInteraction {
    readonly id: `${'S' | 'C'}${string}-I${string}`;
    readonly uuid: QSocketUniqueGenerator<`${'S' | 'C'}${string}-I${string}-M`>;
    private readonly socket;
    private readonly acks;
    private readonly connectedNamespaces;
    private readonly allNamespaces;
    private readonly debuger;
    private readonly interactions;
    protected readonly timeout: TMakeRequired<TMakeRequired<IQSocketConfigBase>['timeout']>;
    private messageBuffer;
    private isProcessing;
    private _dataFormat;
    set dateFormat(dateFormat: EDataFormat);
    constructor(id: `${'S' | 'C'}${string}-I${string}`, socket: TQSocketInteractionInstance, allNamespaces: Map<string, QSocketNamespace> | undefined, interactions: Map<`${'C' | 'S'}${string}-I${string}`, QSocketInteraction>, timeout: TMakeRequired<TMakeRequired<IQSocketConfigBase>['timeout']>, debuger: QSocketDebuger, dateFormat?: EDataFormat);
    static close(interaction: QSocketInteraction): void;
    private closeHandle;
    private onHandle;
    private onControl;
    private onData;
    private onAck;
    send(message: IQSocketProtocolMessage): Promise<void>;
    private sendCumulative;
    sendBuffer(buffer: Uint8Array): void;
    broadcast<O extends IQSocketProtocolPayload = IQSocketProtocolPayload>(message: IQSocketProtocolMessage<IQSocketProtocolMessageMetaData>, timeout?: number): Promise<O[][][]>;
    sendData<O extends IQSocketProtocolPayload = IQSocketProtocolPayload>(message: IQSocketProtocolMessage<IQSocketProtocolMessageMetaData>, timeout?: number): Promise<O[][] | undefined>;
    sendHandshake(message: IQSocketProtocolMessage<IQSocketProtocolMessageMetaAck>, timeout?: number): Promise<IQSocketProtocolPayload<_qsocket_protocol.TQSocketProtocolPayloadData>[][]>;
    sendCommand(message: IQSocketProtocolMessage<IQSocketProtocolMessageMetaControl>, timeout?: number): Promise<IQSocketProtocolMessage<IQSocketProtocolMessageMetaAck>[number]['payload'][][] | void>;
    addAckResolver<O extends IQSocketProtocolPayload = IQSocketProtocolPayload>(message: IQSocketProtocolMessage, prefix: string, timeout?: number): Promise<O[][]>;
    static joinNamespace(interaction: QSocketInteraction, namespace: QSocketNamespace): Promise<void>;
    private joinNamespace;
    static leaveNamespace(interaction: QSocketInteraction, namespace: QSocketNamespace): Promise<void>;
    private leaveNamespace;
}

declare class QSocketEventEmetterBase {
    /**
     * Map of all event listeners, supporting multiple listeners for each event type.
     * @private
     * @type {Map<string, IQSocketListener<any, any>[]>}
     */
    protected readonly listeners: Map<string, IQSocketListener<any, any>[]>;
    /**
     * Listeners for the "connection" event, triggered upon establishing a new connection.
     * @private
     * @type {((connection: QSocketConnection) => void)[]}
     */
    protected readonly connectionListeners: ((connection: QSocketConnection) => void)[];
    /**
     * Listeners for the "disconnection" event, triggered when a connection is terminated.
     * @private
     * @type {(() => void)[]}
     */
    protected readonly disconnectionListeners: (() => void)[];
    protected addEventListener<I extends TQSocketProtocolPayloadData, O extends TQSocketProtocolPayloadData>(event: string, listener: TQSocketListenerCallback<I, O>, type: EQSocketListenerType, contentType?: TQSocketContentType): void;
    protected removeEventListener<I extends TQSocketProtocolPayloadData, O extends TQSocketProtocolPayloadData>(event: string, listener: TQSocketListenerCallback<I, O> | ((connection: QSocketConnection) => void)): void;
    protected executor(chunk: IQSocketProtocolChunk<IQSocketProtocolMessageMetaData>): Promise<IQSocketProtocolMessage<IQSocketProtocolMessageMetaAck>>;
}
declare class QSocketConnectionEventEmitter extends QSocketEventEmetterBase {
    /**
     * Registers a persistent listener for the disconnection event.
     * @example
     * ```typescript
     * emitter.on('disconnection', () => { console.log('Disconnected'); });
     * ```
     * @param {string} event - Event name: 'disconnection'
     * @param {() => void} listener - Callback function executed on disconnection.
     */
    on(event: 'disconnection', listener: () => void): void;
    /**
     * Registers a persistent listener for a custom event.
     * @example
     * ```typescript
     * emitter.on('customEvent', (data) => { console.log('Received data:', data); }, 'application/json', 'utf-8');
     * ```
     * @param {string} event - Custom event name.
     * @param {TQSocketListenerCallback<I, O>} listener - Callback function for the custom event.
     * @param {TQSocketContentType} [contentType] - Optional content type (e.g., 'application/json').
     */
    on<I extends TQSocketProtocolPayloadData, O extends TQSocketProtocolPayloadData>(event: string, listener: TQSocketListenerCallback<I, O>, contentType?: TQSocketContentType): void;
    /**
     * Registers a one-time listener for the disconnection event.
     * @example
     * ```typescript
     * emitter.once('disconnection', () => { console.log('One-time disconnection'); });
     * ```
     * @param {string} event - Event name: 'disconnection'
     * @param {() => void} listener - Callback function executed on disconnection.
     */
    once(event: 'disconnection', listener: () => void): void;
    /**
     * Registers a one-time listener for a custom event.
     * @example
     * ```typescript
     * emitter.once('customEvent', (data) => { console.log('One-time event data:', data); }, 'application/json', 'utf-8');
     * ```
     * @param {string} event - Custom event name.
     * @param {TQSocketListenerCallback<I, O>} listener - Callback function for the custom event.
     * @param {TQSocketContentType} [contentType] - Optional content type.
     */
    once<I extends TQSocketProtocolPayloadData, O extends TQSocketProtocolPayloadData>(event: string, listener: TQSocketListenerCallback<I, O>, contentType?: TQSocketContentType): void;
    /**
     * Removes a listener for the disconnection event.
     * @example
     * ```typescript
     * emitter.off('disconnection', disconnectionHandler);
     * ```
     * @param {string} event - Event name: 'disconnection'
     * @param {() => void} listener - Callback function previously registered for disconnection.
     */
    off(event: 'disconnection', listener: () => void): void;
}
declare abstract class QSocketNamespaceEventEmitter extends QSocketEventEmetterBase {
    /**
     * Registers a persistent listener for the connection event.
     * @example
     * ```typescript
     * emitter.on('connection', (connection: QSocketConnection) => { console.log('Connected:', connection); });
     * ```
     * @param {string} event - Event name: 'connection'
     * @param {(connection: QSocketConnection) => void} listener - Callback function executed on connection.
     */
    on(event: 'connection', listener: (connection: QSocketConnection) => void): void;
    /**
     * Registers a persistent listener for the disconnection event.
     * @example
     * ```typescript
     * emitter.on('disconnection', () => { console.log('Disconnected'); });
     * ```
     * @param {string} event - Event name: 'disconnection'
     * @param {() => void} listener - Callback function executed on disconnection.
     */
    on(event: 'disconnection', listener: () => void): void;
    /**
     * Registers a persistent listener for a custom event.
     * @example
     * ```typescript
     * emitter.on('customEvent', (data) => { console.log('Received data:', data); }, 'application/json', 'utf-8');
     * ```
     * @param {string} event - Custom event name.
     * @param {TQSocketListenerCallback<I, O>} listener - Callback function for the custom event.
     * @param {TQSocketContentType} [contentType] - Optional content type (e.g., 'application/json').
     */
    on<I extends TQSocketProtocolPayloadData, O extends TQSocketProtocolPayloadData>(event: string, listener: TQSocketListenerCallback<I, O>, contentType?: TQSocketContentType): void;
    /**
     * Registers a one-time listener for the connection event.
     * @example
     * ```typescript
     * emitter.once('connection', (connection: QSocketConnection) => { console.log('One-time connection:', connection); });
     * ```
     * @param {string} event - Event name: 'connection'
     * @param {(connection: QSocketConnection) => void} listener - Callback function executed on connection.
     */
    once(event: 'connection', listener: (connection: QSocketConnection) => void): void;
    /**
     * Registers a one-time listener for the disconnection event.
     * @example
     * ```typescript
     * emitter.once('disconnection', () => { console.log('One-time disconnection'); });
     * ```
     * @param {string} event - Event name: 'disconnection'
     * @param {() => void} listener - Callback function executed on disconnection.
     */
    once(event: 'disconnection', listener: () => void): void;
    /**
     * Registers a one-time listener for a custom event.
     * @example
     * ```typescript
     * emitter.once('customEvent', (data) => { console.log('One-time event data:', data); }, 'application/json', 'utf-8');
     * ```
     * @param {string} event - Custom event name.
     * @param {TQSocketListenerCallback<I, O>} listener - Callback function for the custom event.
     * @param {TQSocketContentType} [contentType] - Optional content type.
     */
    once<I extends TQSocketProtocolPayloadData, O extends TQSocketProtocolPayloadData>(event: string, listener: TQSocketListenerCallback<I, O>, contentType?: TQSocketContentType): void;
    /**
     * Removes a listener for the connection event.
     * @example
     * ```typescript
     * emitter.off('connection', connectionHandler);
     * ```
     * @param {string} event - Event name: 'connection'
     * @param {(connection: QSocketConnection) => void} listener - Callback function previously registered for connection.
     */
    off(event: 'connection', listener: (connection: QSocketConnection) => void): void;
    /**
     * Removes a listener for the disconnection event.
     * @example
     * ```typescript
     * emitter.off('disconnection', disconnectionHandler);
     * ```
     * @param {string} event - Event name: 'disconnection'
     * @param {() => void} listener - Callback function previously registered for disconnection.
     */
    off(event: 'disconnection', listener: () => void): void;
    /**
     * Removes a persistent listener for a custom event.
     * @example
     * ```typescript
     * emitter.off('customEvent', (data) => { console.log('Received data:', data); });
     * ```
     * @param {string} event - Custom event name.
     * @param {TQSocketListenerCallback<I, O>} listener - Callback function for the custom event.
     */
    off<I extends TQSocketProtocolPayloadData, O extends TQSocketProtocolPayloadData>(event: string, listener: TQSocketListenerCallback<I, O>): void;
    protected abstract addConnectionListennerHandle(listenner: (connection: QSocketConnection) => void): void;
}

declare class QSocketNamespace extends QSocketNamespaceEventEmitter {
    private readonly _name;
    private readonly connections;
    private readonly debuger;
    private waiter?;
    private waiterWaited?;
    get name(): string;
    constructor(name: string, isActivated: boolean | undefined, debuger: QSocketDebuger);
    emit<I extends TQSocketProtocolPayloadData, O extends TQSocketProtocolPayloadData, P extends IQSocketProtocolPayload<O> = IQSocketProtocolPayload<O>>(event: string, data?: I, options?: {
        timeout?: number;
        contentType?: TQSocketContentType;
    }): Promise<P[][]>;
    static pipe(interaction: QSocketInteraction, namespace: QSocketNamespace, chunk: IQSocketProtocolChunk<IQSocketProtocolMessageMetaData>): Promise<IQSocketProtocolMessage<IQSocketProtocolMessageMetaAck>>;
    static addClient(namespace: QSocketNamespace, interaction: QSocketInteraction): Promise<void>;
    static deleteClient(namespace: QSocketNamespace, interaction: QSocketInteraction): Promise<void>;
    static destroy(namespace: QSocketNamespace): void;
    protected addConnectionListennerHandle(listenner: (connection: QSocketConnection) => void): void;
    static activate(namespace: QSocketNamespace): void;
    static diactivate(namespace: QSocketNamespace): void;
}

declare class QSocketConnection extends QSocketConnectionEventEmitter {
    private interaction;
    private namespace;
    constructor(interaction: QSocketInteraction, namespace: QSocketNamespace);
    /**
     * @description Отправка данных на связанный клиент
     */
    emit<I extends TQSocketProtocolPayloadData, O extends IQSocketProtocolPayload>(event: string, data?: I, options?: {
        timeout?: number;
        contentType?: TQSocketContentType;
    }): Promise<O[]>;
    broadcast<I extends TQSocketProtocolPayloadData, O extends IQSocketProtocolPayload>(event: string, data?: I, options?: {
        timeout?: number;
        contentType?: TQSocketContentType;
    }): Promise<O[][] | undefined>;
    static pipe(connection: QSocketConnection, chunk: IQSocketProtocolChunk<IQSocketProtocolMessageMetaData>): Promise<IQSocketProtocolMessage<IQSocketProtocolMessageMetaAck>>;
    static close(connection: QSocketConnection): void;
}

/**
 * Абстрактный базовый класс для работы с QSocket.
 * Предоставляет методы для управления пространствами имён.
 */
declare abstract class QSocketBase {
    readonly type: 'client' | 'server';
    readonly id: `${'C' | 'S'}${string}`;
    protected readonly uuid: QSocketUniqueGenerator<`${'C' | 'S'}${string}-SM`>;
    protected readonly interactionUUID: QSocketUniqueGenerator<`${'C' | 'S'}${string}-I${string}`>;
    protected readonly namespaces: Map<string, QSocketNamespace>;
    protected readonly debuger: QSocketDebuger;
    protected readonly interactions: Map<`${'C' | 'S'}${string}-I${string}`, QSocketInteraction>;
    private dateFormat;
    protected readonly timeout: TMakeRequired<TMakeRequired<IQSocketConfigBase>['timeout']>;
    private readonly middlewares;
    constructor(type: 'client' | 'server', config?: IQSocketConfigBase);
    protected connectionHandle(socket: TQSocketServerSocket | TQSocketClientSocket): void;
    protected closeInteraction(interactionId: `${'C' | 'S'}${string}-I${string}`, interaction: QSocketInteraction): void;
    /**
     * Создаёт новое пространство имён или возвращает существующее.
     * @param {string} name - Имя создаваемого пространства имён.
     * @returns {QSocketNamespace} Пространство имён QSocket.
     */
    createNamespace(name: string): QSocketNamespace;
    /**
     * Удаляет существующее пространство имён.
     * @param {string} name - Имя удаляемого пространства имён.
     * @returns {boolean} Возвращает `true`, если пространство имён было удалено, иначе `false`.
     */
    deleteNamespace(name: string): Promise<boolean>;
    /**
     * @description Добавляет промежуточный обработчик сообщений
     * @param handler
     */
    use(handler: (message: IQSocketProtocolMessage<IQSocketProtocolMessageMetaData>, socket: TQSocketInteractionInstance) => IQSocketProtocolMessage<IQSocketProtocolMessageMetaData>): void;
    protected namespaceControl(namespace: QSocketNamespace, cmd: 'join-namespace' | 'leave-namespace'): Promise<boolean>;
    /**
     * Изменяет формат передачи данных для всех соединений
     * По умолчанию "binary"
     */
    setDateFormat(dataFormat: 'base64' | 'binary'): void;
}

declare class QSocketClient extends QSocketBase {
    private isConnected;
    private transportBuilder;
    private reconnectionAttempts;
    private reconnecting;
    private reconnectionConfig;
    constructor(socketBuilder: () => TQSocketClientSocket, config?: IQSocketClientConfig);
    connect(): Promise<void>;
    /**
     * Метод для переподключения с учетом конфигурации.
     */
    private attemptReconnect;
    /**
     * Вычисляет задержку для следующей попытки переподключения.
     * @returns {number} Задержка в миллисекундах
     */
    private calculateDelay;
}

declare class QSocketServer extends QSocketBase {
    private server;
    constructor(transport: TQSocketServer, config: IQSocketServerConfig);
}

export { type IQSocketClientConfig, type IQSocketServerConfig, QSocketClient, QSocketConnection, QSocketDebuger, QSocketInteraction, QSocketNamespace, QSocketServer };
