"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SmartWebsocket = void 0;
// Copied from https://github.com/LedgerHQ/eth-dapp-browser/blob/main/src/DAPPBrowserV2/SmartWebsocket.ts
const events_1 = __importDefault(require("events"));
const DEFAULT_RECONNECT = false;
const DEFAULT_RECONNECT_DELAY = 5000;
const DEFAULT_RECONNECT_MAX_ATTEMPTS = 3;
function logger(message, ...args) {
    // eslint-disable-next-line no-console
    console.log(`%c[WEBSOCKET] ${message}`, "background: #eee; color: #F70", ...args);
}
class SmartWebsocket extends events_1.default {
    ws = null;
    url;
    reconnectAttempts = 0;
    _connected = false;
    reconnect;
    reconnectMaxAttempts;
    reconnectDelay;
    logger;
    constructor(url, options) {
        super();
        this.url = url;
        this.logger = options?.logger || logger;
        this.reconnect = options?.reconnect || DEFAULT_RECONNECT;
        this.reconnectMaxAttempts = options?.reconnectMaxAttempts || DEFAULT_RECONNECT_MAX_ATTEMPTS;
        this.reconnectDelay = options?.reconnectDelay || DEFAULT_RECONNECT_DELAY;
    }
    async connect() {
        if (this._connected) {
            return this._connected;
        }
        if (this.reconnectAttempts) {
            this.emit("reconnecting");
            this.logger(`reconnecting (${this.reconnectAttempts}/${this.reconnectMaxAttempts})`);
        }
        else {
            this.emit("connecting");
            this.logger(`connecting to ${this.url}`);
        }
        this._connected = new Promise((resolve, reject) => {
            try {
                const ws = new WebSocket(this.url);
                ws.onopen = () => {
                    this.emit("connected");
                    this.logger("connected");
                    resolve(ws);
                    this.reconnectAttempts = 0;
                };
                ws.onmessage = (event) => {
                    const message = JSON.parse(event.data);
                    this.emit("message", message);
                    this.logger("message", message);
                };
                ws.onclose = event => {
                    this.ws = null;
                    this._connected = false;
                    this.logger("disconnected", event);
                    this.emit("disconnected");
                    if (this.reconnect && !event.wasClean) {
                        if (this.reconnectAttempts < this.reconnectMaxAttempts) {
                            this.reconnectAttempts++;
                            this.logger("will reconnect in 5s");
                            setTimeout(() => {
                                this.connect().then(resolve).catch(reject);
                            }, this.reconnectDelay);
                        }
                        else {
                            reject(new Error(`Max reconnect attempts reached (${this.reconnectMaxAttempts})`));
                            this.logger(`Max reconnect attempts reached (${this.reconnectMaxAttempts})`);
                            this.reconnectAttempts = 0;
                        }
                    }
                    else {
                        reject();
                    }
                };
                this.ws = ws;
            }
            catch (error) {
                reject(error);
            }
        });
        return this._connected;
    }
    async connected() {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            return this.ws;
        }
        else if (this._connected) {
            return this._connected;
        }
        return this.connect();
    }
    async send(message) {
        const ws = await this.connected();
        ws.send(JSON.stringify(message));
        this.logger("sent", message);
    }
    close() {
        if (this.ws) {
            this.logger("closing");
            this.ws.close(1000, "terminated");
        }
        this._connected = false;
    }
}
exports.SmartWebsocket = SmartWebsocket;
//# sourceMappingURL=SmartWebsocket.js.map