"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MotionMasterPubSubWebSocket = void 0;
const rxjs_1 = require("rxjs");
const webSocket_1 = require("rxjs/webSocket");
const logger_1 = require("./logger");
const types_1 = require("./types");
const util_1 = require("./util");
class MotionMasterPubSubWebSocket {
    constructor() {
        this.opened$ = new rxjs_1.BehaviorSubject(false);
        this.close$ = new rxjs_1.Subject();
        this.data$ = new rxjs_1.Subject();
    }
    get url() {
        return this._url;
    }
    open(url) {
        this._url = url;
        this.webSocket$ = this.createWebSocket(url);
        this.webSocket$.subscribe({
            next: (value) => this.data$.next(value),
            error: (err) => {
                console.error(err);
                // ignore, clients will receive close$ event instead
            },
        });
    }
    close() {
        var _a;
        (_a = this.webSocket$) === null || _a === void 0 ? void 0 : _a.complete();
    }
    reopen() {
        if (this.url && this.opened$.value === false) {
            this.open(this.url);
        }
    }
    createWebSocket(url) {
        const decoder = new TextDecoder('utf-8');
        const webSocketConfig = {
            binaryType: 'arraybuffer',
            closeObserver: {
                next: (ev) => {
                    this.opened$.next(false);
                    this.close$.next({ code: ev.code, reason: ev.reason });
                    logger_1.logger.info(`Connection closed ${url}`);
                },
            },
            deserializer: (e) => {
                const end = new Uint8Array(e.data, 0, 1)[0] + 1;
                const topic = decoder.decode(e.data.slice(1, end)); // topic starts from the 2nd byte
                const message = types_1.MotionMasterMessage.decode(new Uint8Array(e.data.slice(end)));
                return [topic, (0, util_1.createPlainObjectFromMotionMasterMessage)(message)];
            },
            openObserver: {
                next: () => {
                    this.opened$.next(true);
                    logger_1.logger.info(`Connection opened ${url}`);
                },
            },
            url,
        };
        return (0, webSocket_1.webSocket)(webSocketConfig);
    }
}
exports.MotionMasterPubSubWebSocket = MotionMasterPubSubWebSocket;
//# sourceMappingURL=motion-master-pub-sub-web-socket.js.map