import SocketOptions from "./SocketOptions";
import { InternalServerTransmits } from "ziron-events";
import { DataType, InvokeListener, ComplexTypesOption, TransmitListener, Transport, BatchOption, ResponseTimeoutOption, ReturnDataTypeOption } from "ziron-engine";
import EventEmitter from "emitix";
import { CancelablePromise } from "../main/utils/CancelablePromise";
import { CancelableOption, SendTimeoutOption } from "../main/Options";
type LocalEventEmitter = EventEmitter<{
    'error': [Error];
    'connect': [any];
    'connectAbort': [number, string];
    'disconnect': [number, string];
    'authTokenChange': [object | null, object | null, boolean];
}>;
export declare const enum SocketConnectionState {
    Open = 0,
    Connecting = 1,
    Closed = 2
}
export declare const enum ChannelState {
    Pending = 0,
    Subscribed = 1
}
export declare const enum UnsubscribeReason {
    Client = 0,
    KickOut = 1,
    BadConnection = 2
}
export type ReceiverListener = (data: any, type: DataType) => void | Promise<void>;
export type ProcedureListener = (data: any, end: (data?: any, processComplexTypes?: boolean) => void, reject: (err?: any) => void, type: DataType) => void | Promise<void>;
type Receivers = {
    readonly [key in InternalServerTransmits]: ReceiverListener;
} & {
    [key: string]: ReceiverListener | undefined;
};
type Procedures = {
    [key: string]: ProcedureListener | undefined;
};
export default class Socket {
    private readonly options;
    private readonly transportOptions;
    private readonly autoReconnectOptions;
    private readonly _stringifiedHandshakeAttachment?;
    private readonly _url;
    private _socket?;
    private _state;
    private _channelMap;
    private readonly _chEmitter;
    /**
     * @description
     * The current max allowed payload size of the server.
     * It will be updated on a connection
     * with the server-side information
     */
    readonly currentMaxPayloadSize: number;
    private _currentPingTimeout;
    private _pingTimeoutTicker;
    private _connectTimeoutTicker;
    private _reconnectTimeoutTicker;
    private _connectDeferred;
    private readonly _tokenStoreEngine;
    private _handshakeAuthToken;
    readonly signedAuthToken: string | null;
    readonly authToken: any | null;
    readonly authenticated: boolean;
    private setAuth;
    readonly reconnectAttempts: number;
    readonly procedures: Procedures;
    /**
     * @description
     * Will be called whenever no corresponding Procedure was found.
     * Can be overridden.
     */
    onUnknownInvoke: InvokeListener;
    readonly receivers: Receivers;
    /**
     * @description
     * Will be called whenever no corresponding Receiver was found.
     * Can be overridden.
     */
    onUnknownTransmit: TransmitListener;
    private readonly _localEmitter;
    readonly once: LocalEventEmitter['once'];
    readonly on: LocalEventEmitter['on'];
    readonly off: LocalEventEmitter['off'];
    private readonly _emit;
    private readonly _transport;
    private readonly _onMessageHandler;
    /**
     * Creates a new Socket with an URL string.
     * With the second parameter, you can specify the socket's options
     * and overwrite parsed information from the URL.
     * @param url
     * @param options
     */
    constructor(url: string, options?: SocketOptions);
    /**
     * Creates a new Socket with specific options.
     * @param options
     */
    constructor(options?: SocketOptions);
    private _updateTransportOptions;
    /**
     * Parses the information from an URL to the socket options.
     * @param url
     */
    static parseOptionsFromUrl(url: string): SocketOptions;
    readonly flushBuffer: Transport['buffer']['flushBuffer'];
    readonly getBufferSize: Transport['buffer']['getBufferSize'];
    readonly sendPackage: Transport['sendPackage'];
    private _onInvoke;
    private _onTransmit;
    connect(timeout?: number): Promise<any>;
    private _loadHandshakeAuthToken;
    /**
     * @param code
     * Codes 1000, 4500 or above 4500 will be treated as permanent disconnects.
     * @param reason
     */
    disconnect(code?: number, reason?: string): void;
    reconnect(connectTimeout?: number): Promise<any>;
    private _tryConnect;
    private _destroyConnection;
    private _renewPingTimeout;
    private _boundPingTimeoutReached;
    private _onPingTimeoutReached;
    private _boundConnectTimeoutReached;
    private _onConnectTimeoutReached;
    private _boundOnSocketOpen;
    private _onSocketOpen;
    private _processOpenAuthTokenState;
    private _boundOnSocketClose;
    private _onSocketClose;
    private _boundOnSocketError;
    private _onSocketError;
    private _boundOnSocketDrain;
    private _onSocketDrain;
    get bufferedSendAmount(): number;
    hasLowSendBackpressure(): boolean;
    private _onConnectAbort;
    private _onDisconnect;
    private _tryReconnect;
    authenticate<C extends boolean | undefined = undefined>(signedAuthToken: string, options: BatchOption & SendTimeoutOption & CancelableOption<C>): C extends true ? CancelablePromise<void> : Promise<void>;
    deauthenticate(): Promise<void>;
    isConnected(): boolean;
    isConnecting(): boolean;
    isClosed(): boolean;
    private _createUrl;
    private _createHandshakeUrl;
    private static _createHandshakeProtocolHeader;
    transmit<C extends boolean | undefined = undefined>(receiver: string, data?: any, options?: BatchOption & SendTimeoutOption & CancelableOption<C> & ComplexTypesOption): C extends true ? CancelablePromise<void> : Promise<void>;
    invoke<RDT extends true | false | undefined, C extends boolean | undefined = undefined>(procedure: string, data?: any, options?: BatchOption & SendTimeoutOption & CancelableOption<C> & ResponseTimeoutOption & ComplexTypesOption & ReturnDataTypeOption<RDT>): C extends true ? CancelablePromise<RDT extends true ? [any, DataType] : any> : Promise<RDT extends true ? [any, DataType] : any>;
    subscribe(channel: string, options?: BatchOption & SendTimeoutOption): Promise<void>;
    private _trySubscribe;
    /**
     * Unsubscribe from all current channels.
     * @param options
     */
    unsubscribe(options?: BatchOption & SendTimeoutOption): any;
    /**
     * Unsubscribe from a specific channel.
     * @param channel
     * @param options
     */
    unsubscribe(channel: string, options?: BatchOption & SendTimeoutOption): any;
    private _unsubscribe;
    hasSubscribed(channel: string, includePending?: boolean): boolean;
    getSubscriptions(includePending?: boolean): string[];
    publish<C extends boolean | undefined = undefined, ACK extends boolean | undefined = undefined>(channel: string, data?: any, options?: BatchOption & SendTimeoutOption & CancelableOption<C> & {
        ack?: boolean;
    } & ComplexTypesOption): C extends true ? CancelablePromise<void> : Promise<void>;
    private _processPendingSubscriptions;
    private _suspendSubscriptions;
    onPublish(abstractListener: (channel: string, data: any, complexDataType: boolean) => any): void;
    onPublish(channel: string, listener: (data: any, complexDataType: boolean) => any): void;
    oncePublish(timeout?: number): Promise<[string, any, boolean]>;
    oncePublish(abstractListener: (channel: string, data: any, complexDataType: boolean) => any): void;
    oncePublish(channel: string, timeout?: number): Promise<[any, boolean]>;
    oncePublish(channel: string, listener: (data: any, complexDataType: boolean) => any): void;
    /**
     * Notice that when you don't provide a channel name,
     * only abstract listeners are affected.
     */
    offPublish(abstractListener?: (channel: string, data: any, complexDataType: boolean) => any): void;
    /**
     * Notice that when you don't provide a channel name,
     * only abstract listeners are affected.
     */
    offPublish(channel: string, listener?: (data: any, complexDataType: boolean) => any): void;
    onSubscribe(abstractListener: (channel: string) => any): void;
    onSubscribe(channel: string, listener: () => any): void;
    onceSubscribe(timeout?: number): Promise<[string]>;
    onceSubscribe(abstractListener: (channel: string) => any): void;
    onceSubscribe(channel: string, timeout?: number): Promise<[]>;
    onceSubscribe(channel: string, listener: () => any): void;
    /**
     * Notice that when you don't provide a channel name,
     * only abstract listeners are affected.
     */
    offSubscribe(abstractListener?: (channel: string) => any): void;
    /**
     * Notice that when you don't provide a channel name,
     * only abstract listeners are affected.
     */
    offSubscribe(channel: string, listener?: () => any): void;
    onUnsubscribe(abstractListener: (channel: string, reason: UnsubscribeReason, data?: any) => any): void;
    onUnsubscribe(channel: string, listener: (reason: UnsubscribeReason, data?: any) => any): void;
    onceUnsubscribe(timeout?: number): Promise<[string, UnsubscribeReason, any]>;
    onceUnsubscribe(abstractListener: (channel: string, reason: UnsubscribeReason, data?: any) => any): void;
    onceUnsubscribe(channel: string, timeout?: number): Promise<[UnsubscribeReason, any]>;
    onceUnsubscribe(channel: string, listener: (reason: UnsubscribeReason, data?: any) => any): void;
    /**
     * Notice that when you don't provide a channel name,
     * only abstract listeners are affected.
     */
    offUnsubscribe(abstractListener?: (channel: string, reason: UnsubscribeReason, data?: any) => any): void;
    /**
     * Notice that when you don't provide a channel name,
     * only abstract listeners are affected.
     */
    offUnsubscribe(channel: string, listener?: (reason: UnsubscribeReason, data?: any) => any): void;
    removeAllChannelListener(): void;
}
export {};
