import { type Message } from './io.common.ts';
import { Lock, TimeoutError } from './utils.common.ts';
/** 对于 request() 函数来说无意义的 headers，会自动过滤掉 */
export declare const drop_request_headers: Set<string>;
export interface BasicAuth {
    type: 'basic';
    username: string;
    password: string;
}
export interface BearerAuth {
    type: 'bearer';
    token: string;
}
/** 自动保持 remote 连接，只对 initiator 且传入 url 有效，
    - 在未连接，或 websocket on_error 检测到连接断开后以 reconnect_interval 间隔尝试 remote.call(func) 重连
    - 在连接状态下以 heartbeat_interval 间隔发送心跳包确保连接状态
    
    配置选项:
    - func?: 连接后调用的函数，通常为某个 register 函数，将自身注册到 server
    - args?: 连接后调用函数时传递的参数，与 func 配合使用
    - reconnect_interval?: `1000 * 5` 首次重连失败后的后续尝试间隔 (单位: ms)
    - heartbeat_interval?: `1000 * 60` 发送心跳包确保连接的间隔 (单位: ms)
    - error_delay?: `2000` 遇到错误时首次尝试重连的延时 (单位: ms) */
export interface RemoteKeeperOptions {
    func?: string;
    args?: any[];
    reconnect_interval?: number;
    heartbeat_interval?: number;
    error_delay?: number;
}
export declare const WebSocketConnecting = 0;
export declare const WebSocketOpen = 1;
export declare const WebSocketClosing = 2;
export declare const WebSocketClosed = 3;
export declare const websocket_states: readonly ["connecting", "open", "closing", "closed"];
export declare class WebSocketConnectionError extends Error {
    name: "WebSocketConnectionError";
    url: string;
    protocols?: string[];
    type?: 'close' | 'error';
    /** close 事件时为 close code (非 1000 的 number), error 事件为 error code (可能是 string) */
    code?: string | number;
    reason?: string;
    event?: CloseEvent | ErrorEvent;
    address?: string;
    errno?: number;
    port?: number;
    syscall?: string;
    static get_reason_string(code: number | string, reason?: string): string | number;
    constructor(url: string, protocols: string[] | undefined, event?: CloseEvent | ErrorEvent, message?: string);
}
/** 连接 websocket url, 设置各种事件监听器。在 open 事件后 resolve, 返回 websocket
    遇到 error, close 事件时会创建 WebSocketConnectionError:
        - reject 掉返回的 promise (若此时未 settle)
        - 作为参数调用 on_error (已 settle 且有 on_error 回调)
    可以用 WebSocket.bufferedAmount 来查询大消息的发送进度
    https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/bufferedAmount
    - url
    - options:
        - print?: 是否打印连接、关闭信息
        - protocols?
        - max_payload?: `8 gb` (仅 nodejs 环境有效)
        - proxy?: string (仅 nodejs 环境有效)
        - on_message: 根据 websocket frame 的 opcode 不同 (text frame 或 binary frame)，event 中的 data 对应为 ArrayBuffer 或者 string
          https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
        - on_error?: 在 websocket 出错和非正常关闭 (close, error 事件) 时都调用，可以根据 error.type 来区分，error 的类型是 WebSocketConnectionError，
            type 为 'close' 时有 code 和 reason 属性
        - on_close?: 和 websocket 的 'close' 事件不相同，只在正常关闭 (close code 为 1000) 时才调用，否则都会调用 on_error
            https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes */
export declare function connect_websocket(url: string | URL, { print, protocols, max_payload, // 8 GB
proxy, on_message, on_error, on_close, }: {
    print?: boolean;
    protocols?: string[];
    max_payload?: number;
    proxy?: string;
    on_message(data: ArrayBuffer | string, websocket: WebSocket): any;
    on_error?(error: WebSocketConnectionError, websocket: WebSocket): any;
    on_close?(event: CloseEvent, websocket: WebSocket): any;
}): Promise<WebSocket>;
/** 接收到消息后的处理函数
    返回值会自动被 await，然后可能被封装为 message 回传 */
export type MessageHandler<TData = any> = (message: Message<TData>, remote: Remote) => void | any | Promise<void | any>;
export interface RemoteOptions {
    /** 对端名称，方便接收端提供更明确的报错信息 */
    name?: string;
    /** 作为 websocket 连接发起方，对端的 url 地址 */
    url?: string;
    /** 作为 websocket 连接接收方，将已有的 websocket 连接转为 rpc 通道 */
    websocket?: WebSocket;
    /** 能被对端调用的函数 */
    funcs?: Remote['funcs'];
    /** `false` 是否启用主动探测连接，在连接状态下以 30s 间隔发送心跳包确保连接状态 */
    probe?: boolean;
    /** websocket 连接建立成功时调用对端 register 函数的参数 (仅发起方有效) */
    args?: any[];
    /** `true` 是否打印连接信息、错误信息 */
    print?: boolean;
    /** `false` 打印所有交互的 rpc messages */
    verbose?: boolean;
    /** 使用者自定义的在 websocket 连接出错时，或者 handlers 出错时的处理
        用户设置后会覆盖默认的 print 错误功能 */
    on_error?(error: WebSocketConnectionError | Error, remote: Remote): void;
    /** 使用者自定义的，在重连之前调用的函数，比如可以修改 url，仅连接发起方有效 */
    on_reconnect?(this: Remote): Promise<void>;
}
/** 通过创建 remote 对象对 websocket rpc 进行抽象
    使用 remote.call() 进行一元 rpc
    使用 remote.send() 结合 message.id 进行复杂 rpc
    
    可传入 funcs 注册函数，使得对端能调用，传入后，
    连接发起方在检测到连接断开后间隔 2s (首次) / 10s 尝试重连
    
    可启用 probe 选项启用主动探测连接，进一步确保连接可靠性
    
    有两种创建方法:
    - 传入 url 主动创建 websocket 连接
        创建后等到首个 remote.call 或 remote.send 时建立实际 websocket 连接
    - 传入 websocket，监听事件，将已有的 websocket 连接转为 rpc 通道
    
    rpc 状态与底层连接的状态无关，如果是发起方，remote.send 时检测到断线会自动尝试建立新的 websocket 连接 */
export declare class Remote {
    /** 对端名称，方便接收端提供更明确的报错信息 */
    name?: string;
    /** 作为 websocket 连接发起方，对端的 url 地址 */
    url?: string;
    /** 能被对端调用的函数 */
    funcs: Record<string, MessageHandler>;
    /** `false` 是否启用主动探测连接，在连接状态下以 30s 间隔发送心跳包确保连接状态 */
    probe: boolean;
    /** websocket 连接建立成功时调用对端 register 函数的参数 (仅发起方有效) */
    args?: any[];
    /** `true` 是否打印连接信息、错误信息 */
    print: boolean;
    /** `false` 打印所有交互的 rpc messages */
    verbose: boolean;
    /** 防止作为 websocket 连接发起方时并发创建 websocket 连接 */
    lwebsocket: Lock<WebSocket>;
    /** map<id, message handler>: 通过 (rpc message).id 找到对应的 handler
        一元 rpc 接收方不需要设置 handlers, 发送方需要 */
    handlers: Map<number, MessageHandler<any>>;
    /** 是否正在定时主动检测重连 */
    probing: boolean;
    /** websocket 检测到错误，_on_error 被调用，此时会尝试一段时间后重连 */
    reconnecting: NodeJS.Timeout;
    /** 用户是否手动调用了 disconnect() 主动断开了连接 (仅发起方有效) */
    disconnected: boolean;
    /** on_error 接收到的，正常 websocket 连接发生的首个非 TimeoutError 错误 */
    error: WebSocketConnectionError | Error;
    /** 作为 websocket 连接发起方，传入 url
        作为 websocket 连接接收方，传入 websocket + name */
    constructor({ name, url, websocket, funcs, print, verbose, probe, args, on_error, on_reconnect }?: RemoteOptions);
    /** 统一处理首次连接和连接后的 websocket 错误 */
    _on_error: (error: WebSocketConnectionError | Error) => void;
    on_reconnect?: (this: Remote) => Promise<void>;
    reconnect: () => Promise<void>;
    _on_message: (data: ArrayBuffer) => void;
    /** 使用者自定义的在 websocket 连接出错时，或者 handlers 出错时的处理
        用户设置后会覆盖默认的 print 错误功能 */
    on_error(error: WebSocketConnectionError | Error, remote: Remote): void;
    print_error(error: WebSocketConnectionError | Error): void;
    /** 检查是否已经有 error, websocket 状态是否正常 (open | connecting)
        返回 true: 连接正常，false: 连接异常 */
    check_connection(): boolean;
    /** 幂等，保证 websocket 已连接，否则抛出异常
        通常用于手动建立 websocket 连接并确保成功
        连接断开后，作为发起方会自动创建新的 websocket 连接;
        作为接收方只会检查连接状态，在断开时抛出异常
        保存的 rpc 状态在 this.handlers, 与 websocket 无关，因此即使断开重连也不影响 rpc 的运行，即
        底层连接断开后自动重连对上层应该是无感知的，除非再次连接时失败 */
    connect(): Promise<void>;
    _connect: () => Promise<void>;
    /** 尝试建立连接，通常用于开始保活
        重连错误会在 this.connect 里面调用 this._on_error 处理 */
    try_connect(): Promise<void>;
    /** 开始心跳保活 */
    probe_connection(print_timeout?: boolean): Promise<void>;
    /** 检测连接，返回连接错误，出错时触发 on_error 打印错误信息
        返回值:
        - 连接正常返回: undefined
        - 连接错误返回: 实际的连接错误，通常是 WebSocketConnectionError | TimeoutError */
    test(print_timeout?: boolean): Promise<WebSocketConnectionError | TimeoutError | Error>;
    /** 手动关闭到对端的 websocket 连接 */
    disconnect(): void;
    /** 发送 message 到对端 remote
        发送或连接出错时自动清理 message.id 对应的 handler */
    send(message: Message): Promise<void>;
    /** 能发就发一下，忽略发送失败, best effort */
    try_send(message: Message): void;
    /** 处理接收到的 websocket message 并解析, 根据 message.id 或 message.func 分发到对应的 handler 进行处理，
        handler 处理完成后:
        - 传了 func: 调用函数的情况下 (通常是一元 rpc)，总是将返回值包装为 message 回传
        - 未传 func: 通过 id 调用，如果 handler 返回非 undefined 的值，也包装为 message 回传
        
        如果 message.done == true 则对端指示当前 remote 可以清理 handler
        使用 Uint8Array 作为参数更灵活 https://stackoverflow.com/a/74505197/7609214
        这个方法一般不会抛出错误，也不需要 await，一般在 websocket on_message 时使用 */
    handle(data: Uint8Array): Promise<void>;
    /** 调用对端 remote 中的 func, 只适用于最简单的一元 rpc (请求, 响应) */
    call<TReturn = any>(func: string, args?: any[]): Promise<TReturn>;
    /** 调用对端 remote 中的 func, 开始订阅并接收连续的消息 (订阅流)
        - func: 订阅处理函数
        - on_data: 接收开始订阅后的数据
        - options?:
            - on_error?: 处理开始订阅后的错误 */
    subscribe<TData, TSubscribed = void>(func: string, on_data: (data: TData) => void, on_error?: Remote['on_error']): Promise<{
        id: number;
        data: TSubscribed;
    }>;
}
