import { once } from 'node:events';
import { debuglog } from 'node:util';
import { Connection, Multiplexer, createConnection, createSSLConnection } from 'thrift';
import { isObject, getServiceName, getClient } from './utils.js';
import { DEFAULT_PROTOCOL, DEFAULT_TRANSPORT } from './options.js';
/** 创建客户端 */
export function createClient(options) {
    const { host, port, tls, ...opt } = options ?? { port: 4000 };
    let logger = debuglog(`cloudpss/rpc-client-${port}`, (l) => (logger = l));
    const _host = host ? String(host) : '127.0.0.1';
    const _port = Number.parseInt(String(port ?? '4000'));
    if (!Number.isInteger(_port) || _port <= 0 || _port > 65535) {
        throw new TypeError(`Invalid port rpc ${String(port)}`);
    }
    logger('resolved host=%s, port=%d', _host, _port);
    const _tls = isObject(tls) ? tls : tls ? {} : undefined;
    opt.max_attempts ??= Number.POSITIVE_INFINITY;
    opt.retry_max_delay ??= 5000;
    opt.transport ??= DEFAULT_TRANSPORT;
    opt.protocol ??= DEFAULT_PROTOCOL;
    const connection = (_tls ? createSSLConnection(_host, _port, { ...opt, ..._tls }) : createConnection(_host, _port, opt));
    connection.on('error', (ex) => logger(`error: %s`, ex));
    connection.on('close', () => logger(`closed`));
    connection.on('reconnecting', ({ delay, attempt }) => logger(`reconnecting in %dms, attempt %d`, delay, attempt));
    connection.on('connect', () => logger(`connected`));
    const multiplexer = new Multiplexer();
    const clients = new Map();
    Object.defineProperties(connection, {
        get: {
            value: function get(name, module) {
                if (!name) {
                    throw new TypeError(`Invalid empty name`);
                }
                if (typeof name == 'string') {
                    // OK
                }
                else if (isObject(name)) {
                    // 第二种签名
                    module = name;
                    name = getServiceName(module);
                }
                else {
                    throw new TypeError(`Invalid name ${String(name)}, string expected`);
                }
                let service = clients.get(name);
                if (service != null) {
                    return service;
                }
                if (module == null) {
                    throw new Error(`Service with name "${name}" has not created`);
                }
                const client = getClient(module);
                service = multiplexer.createClient(name, client, this);
                clients.set(name, service);
                logger(`service %s created`, name);
                return service;
            },
        },
        has: {
            value: function (name) {
                return clients.get(name) != null;
            },
        },
        end: {
            value: async function () {
                logger(`ending`);
                Connection.prototype.end.call(this);
                await once(this, 'close');
            },
        },
    });
    return connection;
}
//# sourceMappingURL=client.js.map