"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RainwaySDK = void 0;
const ref_napi_1 = __importDefault(require("ref-napi"));
const ffi_napi_1 = require("ffi-napi");
const events_1 = require("./events");
const rainway_ffi_1 = require("./rainway-ffi");
const rainway_connection_1 = require("./rainway-connection");
const native_1 = require("./native");
const version_1 = require("./version");
const constants_1 = require("./constants");
const impls_1 = require("./events/impls");
const Callback_RainwayPeerId__RainwayError_1 = require("./callbacks/Callback_RainwayPeerId__RainwayError");
const models_1 = require("./models");
/**
 * The Rainway SDK
 */
class RainwaySDK extends events_1.EventEmitter {
    /** @internal */
    constructor() {
        super();
        const defaultLogLevel = rainway_ffi_1.RainwayLogLevel.Info;
        native_1.native.rainway_set_log_level(defaultLogLevel, null);
        this._logLevel = defaultLogLevel;
        this._logCallback = new ffi_napi_1.Callback(ref_napi_1.default.types.void, [rainway_ffi_1.RainwayLogLevelDef, ref_napi_1.default.types.CString, ref_napi_1.default.types.CString], (level, target, message) => {
            if (this)
                this.emit("log", new impls_1.LogEvent(new models_1.LogBody(level, target !== null && target !== void 0 ? target : "", message !== null && message !== void 0 ? message : "")));
        });
        native_1.native.rainway_set_log_sink(this._logCallback);
        (0, native_1.invokeOrError)("rainway_init", () => native_1.native.rainway_init(new rainway_ffi_1.RainwayInitConfigDef({
            userAgent: `RainwaySDK/${version_1.VERSION} Node.js/${process.version}`,
        }).ref()));
        this.isInitialized = true;
    }
    /**
     * Get or set the native library log level.
     */
    get logLevel() {
        return this._logLevel;
    }
    set logLevel(level) {
        native_1.native.rainway_set_log_level(level, null);
        this._logLevel = level;
    }
    /**
     * Get the native library version.
     * A SemVer (https://semver.org/) string.
     */
    get version() {
        // this cannot actually be null
        return native_1.native.rainway_version();
    }
    /**
     * Connects to the Rainway network, creating a {@link RainwayConnection} if successful.
     * This is the first step required to connect to other {@link Peer}s on the Rainway network, or to allow them to connect to you.
     * @param options - connection options
     * @returns A new connection
     */
    connect(options) {
        return __awaiter(this, void 0, void 0, function* () {
            const cb = new Callback_RainwayPeerId__RainwayError_1.Callback_RainwayPeerId__RainwayError();
            (0, native_1.invokeOrError)("rainway_create_connection", () => {
                var _a;
                return native_1.native.rainway_create_connection(new rainway_ffi_1.RainwayCreateConnectionOptionsDef(Object.assign(Object.assign({}, options), { externalId: (_a = options.externalId) !== null && _a !== void 0 ? _a : "", advanced: new rainway_ffi_1.RainwayCreateConnectionAdvancedOptionsDef({
                        endpoint: constants_1.SDK_GATEWAY_URL,
                        forceNewId: false,
                    }), callbackState: cb.callbackState })).ref());
            });
            return cb.promise.then((v) => {
                return new rainway_connection_1.RainwayConnection(v, options.externalId);
            });
        });
    }
}
exports.RainwaySDK = RainwaySDK;
/**
 * Entrypoint and native library facilities for the Rainway SDK.
 */
const rainway = new RainwaySDK();
exports.default = rainway;
//# sourceMappingURL=index.js.map