"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClientWatch = exports.WebSocketServerClient = exports.clsstream = void 0;
const SocketMessage_1 = require("./SocketMessage");
const Message_1 = require("./Messages/Message");
const Config_1 = require("./Config");
const amqpwrapper_1 = require("./amqpwrapper");
const openflow_api_1 = require("@openiap/openflow-api");
const Logger_1 = require("./Logger");
const WebSocketServer_1 = require("./WebSocketServer");
const WebServer_1 = require("./WebServer");
const Semaphore = (n) => ({
    n,
    async down() {
        while (this.n <= 0)
            await this.wait();
        this.n--;
    },
    up() {
        this.n++;
    },
    async wait() {
        if (this.n <= 0)
            return await new Promise((res, req) => {
                setImmediate(async () => res(await this.wait()));
            });
        return;
    },
});
const semaphore = Semaphore(1);
class clsstream {
}
exports.clsstream = clsstream;
class WebSocketServerClient {
    constructor() {
        this._receiveQueue = [];
        this._sendQueue = [];
        this.messageQueue = {};
        this.remoteip = "unknown";
        this.created = new Date();
        this.lastheartbeat = new Date();
        this.lastheartbeatstr = new Date().toISOString();
        this.lastheartbeatsec = "0";
        this.metrics = "";
        this.id = "";
        this._queues = [];
        this._queuescounter = 0;
        this._queuescurrent = 0;
        this._queuescounterstr = "0";
        this._queuescurrentstr = "0";
        this._exchanges = [];
        this.devnull = false;
        this._message = null;
        this._error = null;
        this._close = null;
        this._amqpdisconnected = null;
        this._dbdisconnected = null;
        this._dbconnected = null;
        this.init_complete = false;
        this.watches = {};
    }
    static remoteip(req) {
        if (req == null)
            return "unknown";
        let remoteip = req.socket.remoteAddress;
        if (req.headers["X-Forwarded-For"] != null)
            remoteip = req.headers["X-Forwarded-For"];
        if (req.headers["X-real-IP"] != null)
            remoteip = req.headers["X-real-IP"];
        if (req.headers["x-forwarded-for"] != null)
            remoteip = req.headers["x-forwarded-for"];
        if (req.headers["x-real-ip"] != null)
            remoteip = req.headers["x-real-ip"];
        return remoteip;
    }
    async Initialize(socketObject, req) {
        const span = Logger_1.Logger.otel.startSpanExpress("WebSocketServerClient.Initialize", req);
        try {
            this._socketObject = socketObject;
            this._message = this.message.bind(this);
            this._error = this.error.bind(this);
            this._close = this.close.bind(this);
            this._socketObject.on("message", this._message);
            this._socketObject.on("error", this._error);
            this._socketObject.on("close", this._close);
            this._dbdisconnected = this.dbdisconnected.bind(this);
            this._dbconnected = this.dbconnected.bind(this);
            this._amqpdisconnected = this.amqpdisconnected.bind(this);
            this.id = openflow_api_1.NoderedUtil.GetUniqueIdentifier();
            if (!openflow_api_1.NoderedUtil.IsNullUndefinded(req)) {
                this.remoteip = WebSocketServerClient.remoteip(req);
            }
            let _remoteip = "unknown";
            if (Config_1.Config.otel_trace_connection_ips) {
                _remoteip = _remoteip.split(":").join("-");
            }
            if (!WebSocketServer_1.WebSocketServer.total_connections_count[_remoteip])
                WebSocketServer_1.WebSocketServer.total_connections_count[_remoteip] = 0;
            WebSocketServer_1.WebSocketServer.total_connections_count[_remoteip]++;
            if (await WebServer_1.WebServer.isBlocked(req)) {
                if (Config_1.Config.log_blocked_ips)
                    Logger_1.Logger.instanse.error(this.remoteip + " is blocked", null);
                try {
                    if (Config_1.Config.client_disconnect_signin_error) {
                        this._socketObject.close();
                        return false;
                    }
                }
                catch (error) {
                    Logger_1.Logger.instanse.error(error, null);
                }
                return true;
            }
            else {
                if (Config_1.Config.socket_rate_limit) {
                    try {
                        await WebSocketServer_1.WebSocketServer.BaseRateLimiter.consume(this.remoteip);
                    }
                    catch (error) {
                        Logger_1.Logger.instanse.error(error, null);
                        this._socketObject.close();
                        return false;
                    }
                }
            }
            Logger_1.Logger.instanse.debug("new client " + this.id + " from " + this.remoteip, span, Logger_1.Logger.parsecli(this));
            Config_1.Config.db.on("disconnected", this._dbdisconnected);
            Config_1.Config.db.on("connected", this._dbconnected);
            amqpwrapper_1.amqpwrapper.Instance().on("disconnected", this._amqpdisconnected);
            this.init_complete = true;
            this.ProcessQueue(null);
        }
        catch (error) {
            Logger_1.Logger.instanse.error(error, span);
        }
        finally {
            Logger_1.Logger.otel.endSpan(span);
        }
        return true;
    }
    async dbdisconnected(e) {
        var keys = Object.keys(this.watches);
        for (var i = 0; i < keys.length; i++) {
            let id = keys[i];
            let w = this.watches[id];
            await this.Watch(w.aggregates, w.collectionname, this.jwt, id);
        }
    }
    dbconnected(e) {
    }
    amqpdisconnected(e) {
        for (var i = 0; i < this._queues.length; i++) {
            let msg = SocketMessage_1.SocketMessage.fromcommand("queueclosed");
            let q = new openflow_api_1.QueueClosedMessage();
            q.queuename = this._queues[i].queue;
            msg.data = JSON.stringify(q);
            this._socketObject.send(msg.tojson());
            Logger_1.Logger.instanse.debug("Send queue closed message to " + this.id + " for queue " + q.queuename, null, Logger_1.Logger.parsecli(this));
        }
        for (var i = 0; i < this._exchanges.length; i++) {
            let msg = SocketMessage_1.SocketMessage.fromcommand("exchangeclosed");
            let q = new openflow_api_1.ExchangeClosedMessage();
            q.queuename = this._exchanges[i].queue.queue;
            q.exchangename = this._exchanges[i].exchange;
            msg.data = JSON.stringify(q);
            this._socketObject.send(msg.tojson());
            Logger_1.Logger.instanse.debug("Send queue closed message to " + this.id + " for exchange " + q.exchangename, null, Logger_1.Logger.parsecli(this));
        }
        this._exchanges = [];
        this.CloseConsumers(null);
    }
    close(e) {
        Logger_1.Logger.instanse.debug("Connection closed " + e + " " + this.id + "/" + this.clientagent, null, Logger_1.Logger.parsecli(this));
        this.init_complete = false;
        // this.Close(null);
    }
    error(e) {
        Logger_1.Logger.instanse.error(e, null, Logger_1.Logger.parsecli(this));
    }
    queuecount() {
        if (this._queues == null)
            return 0;
        return this._queues.length;
    }
    connected() {
        if (this._socketObject == null)
            return false;
        if (this._socketObject.readyState === this._socketObject.OPEN || this._socketObject.readyState === this._socketObject.CONNECTING) {
            return true;
        }
        return false;
    }
    ping(parent) {
        const span = (Config_1.Config.otel_trace_pingclients && parent != null ? Logger_1.Logger.otel.startSubSpan("WebSocketServerClient.ping", parent) : null);
        try {
            let msg = SocketMessage_1.SocketMessage.fromcommand("ping");
            if (this._socketObject == null) {
                if (this.queuecount() > 0) {
                    this.CloseConsumers(span);
                }
                return;
            }
            if (this._socketObject.readyState === this._socketObject.CLOSED || this._socketObject.readyState === this._socketObject.CLOSING) {
                if (this.queuecount() > 0) {
                    this.CloseConsumers(span);
                }
                return;
            }
        }
        catch (error) {
            Logger_1.Logger.instanse.error(error, span, Logger_1.Logger.parsecli(this));
            this._receiveQueue = [];
            this._sendQueue = [];
            if (this._socketObject != null) {
                this.Close(span).catch((err) => {
                    Logger_1.Logger.instanse.error(error, span, Logger_1.Logger.parsecli(this));
                });
            }
        }
        finally {
            Logger_1.Logger.otel.endSpan(span);
        }
    }
    message(message) {
        try {
            Logger_1.Logger.instanse.silly("WebSocket message received " + message, null, Logger_1.Logger.parsecli(this));
            let msg = SocketMessage_1.SocketMessage.fromjson(message);
            Logger_1.Logger.instanse.silly("WebSocket message received id: " + msg.id + " index: " + msg.index + " count: " + msg.count, null, Logger_1.Logger.parsecli(this));
            this.lastheartbeat = new Date();
            this.lastheartbeatstr = new Date().toISOString();
            const now = new Date();
            const seconds = (now.getTime() - this.lastheartbeat.getTime()) / 1000;
            this.lastheartbeatsec = seconds.toString();
            this._receiveQueue.push(msg);
            if ((msg.index + 1) >= msg.count)
                this.ProcessQueue(null);
        }
        catch (error) {
            Logger_1.Logger.instanse.error(error, null, Logger_1.Logger.parsecli(this));
            try {
                const errormessage = new Message_1.Message();
                errormessage.command = "error";
                errormessage.data = (error.message ? error.message : error);
                this._socketObject.send(JSON.stringify(errormessage));
            }
            catch (error) {
            }
        }
    }
    async CloseConsumers(parent) {
        await semaphore.down();
        for (let i = this._queues.length - 1; i >= 0; i--) {
            try {
                // await this.CloseConsumer(this._queues[i]);
                await amqpwrapper_1.amqpwrapper.Instance().RemoveQueueConsumer(this.user, this._queues[i], undefined);
                this._queues.splice(i, 1);
                this._queuescurrent--;
                this._queuescurrentstr = this._queuescurrent.toString();
            }
            catch (error) {
                Logger_1.Logger.instanse.error(error, parent, Logger_1.Logger.parsecli(this));
            }
        }
        semaphore.up();
    }
    async Close(parent) {
        const span = Logger_1.Logger.otel.startSubSpan("WebSocketServerClient.Close", parent);
        try {
            this.init_complete = false;
            if (this._dbdisconnected != null)
                Config_1.Config.db.removeListener("disconnected", this._dbdisconnected);
            if (this._dbconnected != null)
                Config_1.Config.db.removeListener("connected", this._dbconnected);
            if (this._message != null)
                Config_1.Config.db.removeListener("disconnected", this._message);
            if (this._error != null)
                Config_1.Config.db.removeListener("disconnected", this._error);
            if (this._close != null)
                Config_1.Config.db.removeListener("disconnected", this._close);
            await this.CloseConsumers(span);
            if (!openflow_api_1.NoderedUtil.IsNullUndefinded(this._socketObject)) {
                try {
                    this._socketObject.close();
                }
                catch (error) {
                    Logger_1.Logger.instanse.error(error, span, Logger_1.Logger.parsecli(this));
                }
            }
            try {
                if (this._amqpdisconnected != null)
                    amqpwrapper_1.amqpwrapper.Instance().removeListener("disconnected", this._amqpdisconnected);
            }
            catch (error) {
                Logger_1.Logger.instanse.error(error, span, Logger_1.Logger.parsecli(this));
            }
            var keys = Object.keys(this.watches);
            for (var i = 0; i < keys.length; i++) {
                await this.UnWatch(keys[i], this.jwt);
            }
            var keys = Object.keys(this.messageQueue);
            for (var i = 0; i < keys.length; i++) {
                delete this.messageQueue[keys[i]].cb;
                delete this.messageQueue[keys[i]];
            }
        }
        catch (error) {
            Logger_1.Logger.instanse.error(error, span, Logger_1.Logger.parsecli(this));
            throw error;
        }
        finally {
            Logger_1.Logger.otel.endSpan(span);
        }
    }
    async CloseConsumer(user, queuename, parent) {
        const span = Logger_1.Logger.otel.startSubSpan("WebSocketServerClient.CloseConsumer", parent);
        await semaphore.down();
        try {
            var old = this._queues.length;
            for (let i = this._queues.length - 1; i >= 0; i--) {
                const q = this._queues[i];
                if (q && (q.queue == queuename || q.queuename == queuename)) {
                    try {
                        amqpwrapper_1.amqpwrapper.Instance().RemoveQueueConsumer(user, this._queues[i], span).catch((err) => {
                            Logger_1.Logger.instanse.error(err, span, Logger_1.Logger.parsecli(this));
                        });
                        this._queues.splice(i, 1);
                        this._queuescurrent--;
                        this._queuescurrentstr = this._queuescurrent.toString();
                    }
                    catch (error) {
                        Logger_1.Logger.instanse.error(error, span, Logger_1.Logger.parsecli(this));
                    }
                }
            }
        }
        catch (error) {
            throw error;
        }
        finally {
            semaphore.up();
            Logger_1.Logger.otel.endSpan(span);
        }
    }
    async RegisterExchange(user, exchangename, algorithm, routingkey = "", addqueue, parent) {
        var _a;
        const span = Logger_1.Logger.otel.startSubSpan("WebSocketServerClient.CreateConsumer", parent);
        try {
            let exclusive = false; // Should we keep the queue around ? for robots and roles
            let exchange = exchangename;
            if (openflow_api_1.NoderedUtil.IsNullEmpty(exchange)) {
                if (this.clientagent == "nodered") {
                    exchange = "nodered." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                    exclusive = true;
                }
                else if (this.clientagent == "webapp") {
                    exchange = "webapp." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                    exclusive = true;
                }
                else if (this.clientagent == "openrpa") {
                    exchange = "openrpa." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                    exclusive = true;
                }
                else if (this.clientagent == "powershell") {
                    exchange = "powershell." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                    exclusive = true;
                }
                else {
                    exchange = "unknown." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                    exclusive = true;
                }
            }
            let exchangequeue = null;
            try {
                const AssertExchangeOptions = Object.assign({}, (amqpwrapper_1.amqpwrapper.Instance().AssertExchangeOptions));
                AssertExchangeOptions.exclusive = exclusive;
                exchangequeue = await amqpwrapper_1.amqpwrapper.Instance().AddExchangeConsumer(user, exchange, algorithm, routingkey, AssertExchangeOptions, this.jwt, addqueue, async (msg, options, ack, done) => {
                    let span;
                    const _data = msg;
                    try {
                        span = Logger_1.Logger.otel.startSpan("WebSocketServerClient.RegisterExchange", msg.traceId, msg.spanId);
                        const result = await this.Queue(msg, exchange, options, span);
                        done(result);
                        ack();
                    }
                    catch (error) {
                        setTimeout(() => {
                            ack(false);
                            Logger_1.Logger.instanse.error(exchange + " failed message queue message, nack and re queue message: ", span, Logger_1.Logger.parsecli(this));
                            Logger_1.Logger.instanse.error(error, span, Logger_1.Logger.parsecli(this));
                        }, Config_1.Config.amqp_requeue_time);
                    }
                    finally {
                        span === null || span === void 0 ? void 0 : span.end();
                    }
                }, span);
                if (exchangequeue) {
                    await semaphore.down();
                    if (exchangequeue.queue)
                        exchange = exchangequeue.queue.queue;
                    this._exchanges.push(exchangequeue);
                    if (exchangequeue.queue) {
                        this._queues.push(exchangequeue.queue);
                        this._queuescounter++;
                        this._queuescurrent++;
                    }
                    this._queuescounterstr = this._queuescounter.toString();
                    this._queuescurrentstr = this._queuescurrent.toString();
                }
            }
            catch (error) {
                Logger_1.Logger.instanse.error(error, span, Logger_1.Logger.parsecli(this));
            }
            if (exchangequeue)
                semaphore.up();
            if (exchangequeue != null)
                return { exchangename: exchangequeue.exchange, queuename: (_a = exchangequeue.queue) === null || _a === void 0 ? void 0 : _a.queue };
            return null;
        }
        catch (error) {
            throw error;
        }
        finally {
            Logger_1.Logger.otel.endSpan(span);
        }
    }
    async CreateConsumer(queuename, parent) {
        const span = Logger_1.Logger.otel.startSubSpan("WebSocketServerClient.CreateConsumer", parent);
        try {
            let exclusive = false; // Should we keep the queue around ? for robots and roles
            let qname = queuename;
            if (openflow_api_1.NoderedUtil.IsNullEmpty(qname)) {
                if (this.clientagent == "nodered") {
                    qname = "nodered." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                    exclusive = true;
                }
                else if (this.clientagent == "webapp") {
                    qname = "webapp." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                    exclusive = true;
                }
                else if (this.clientagent == "openrpa") {
                    qname = "openrpa." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                    exclusive = true;
                }
                else if (this.clientagent == "powershell") {
                    qname = "powershell." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                    exclusive = true;
                }
                else {
                    qname = "unknown." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                    exclusive = true;
                }
            }
            await this.CloseConsumer(this.user, qname, span);
            let queue = null;
            try {
                const AssertQueueOptions = Object.assign({}, (amqpwrapper_1.amqpwrapper.Instance().AssertQueueOptions));
                AssertQueueOptions.exclusive = exclusive;
                if (openflow_api_1.NoderedUtil.IsNullEmpty(queuename)) {
                    AssertQueueOptions.autoDelete = true;
                }
                var exists = this._queues.filter(x => x.queuename == qname || x.queue == qname);
                if (exists.length > 0) {
                    Logger_1.Logger.instanse.warn(qname + " already exists, removing before re-creating", span);
                    for (let i = 0; i < exists.length; i++) {
                        await amqpwrapper_1.amqpwrapper.Instance().RemoveQueueConsumer(this.user, exists[i], span);
                    }
                }
                queue = await amqpwrapper_1.amqpwrapper.Instance().AddQueueConsumer(this.user, qname, AssertQueueOptions, this.jwt, async (msg, options, ack, done) => {
                    // const _data = msg;
                    let span = null;
                    var _data = msg;
                    try {
                        var o = msg;
                        if (typeof o === 'string')
                            o = JSON.parse(o);
                        span = Logger_1.Logger.otel.startSpan("OpenFlow Queue Process Message", o.traceId, o.spanId);
                        Logger_1.Logger.instanse.verbose("[preack] queuename: " + queuename + " qname: " + qname + " replyto: " + options.replyTo + " correlationId: " + options.correlationId, span);
                        _data = await this.Queue(msg, qname, options, span);
                        ;
                        ack();
                        // const result = await this.Queue(msg, qname, options);
                        // done(result);
                        Logger_1.Logger.instanse.debug("[ack] queuename: " + queuename + " qname: " + qname + " replyto: " + options.replyTo + " correlationId: " + options.correlationId, span);
                    }
                    catch (error) {
                        setTimeout(() => {
                            ack(false);
                            Logger_1.Logger.instanse.warn("[nack] queuename: " + queuename + " qname: " + qname + " replyto: " + options.replyTo + " correlationId: " + options.correlationId + " error: " + (error.message ? error.message : error), span);
                        }, Config_1.Config.amqp_requeue_time);
                    }
                    finally {
                        Logger_1.Logger.otel.endSpan(span);
                        try {
                            done(_data);
                        }
                        catch (error) {
                        }
                    }
                }, span);
                if (queue) {
                    await semaphore.down();
                    qname = queue.queue;
                    this._queuescounter++;
                    this._queuescurrent++;
                    this._queuescounterstr = this._queuescounter.toString();
                    this._queuescurrentstr = this._queuescurrent.toString();
                    this._queues.push(queue);
                }
            }
            catch (error) {
                throw error;
            }
            finally {
                if (queue)
                    semaphore.up();
            }
            if (queue != null) {
                return queue.queue;
            }
            return null;
        }
        catch (error) {
            throw error;
        }
        finally {
            Logger_1.Logger.otel.endSpan(span);
        }
    }
    sleep(ms) {
        return new Promise(resolve => {
            setTimeout(resolve, ms);
        });
    }
    ProcessQueue(parent) {
        if (this.devnull) {
            this._receiveQueue = [];
            this._sendQueue = [];
            return;
        }
        if (!this.init_complete) {
            return;
        }
        const span = Logger_1.Logger.otel.startSubSpan("WebSocketServerClient.ProcessQueue", parent);
        try {
            let username = "Unknown";
            if (!openflow_api_1.NoderedUtil.IsNullUndefinded(this.user)) {
                username = this.user.username;
            }
            let ids = [];
            this._receiveQueue.forEach(msg => {
                if (ids.indexOf(msg.id) === -1) {
                    ids.push(msg.id);
                }
            });
            ids.forEach(id => {
                const msgs = this._receiveQueue.filter(function (msg) { return msg.id === id; });
                if (this._receiveQueue.length > Config_1.Config.websocket_max_package_count) {
                    if (Config_1.Config.websocket_disconnect_out_of_sync) {
                        Logger_1.Logger.instanse.error("_receiveQueue containers more than " + Config_1.Config.websocket_max_package_count + " messages for id '" + id + "', disconnecting", span, Logger_1.Logger.parsecli(this));
                        this.Close(span);
                    }
                    else {
                        Logger_1.Logger.instanse.error("_receiveQueue containers more than " + Config_1.Config.websocket_max_package_count + " messages for id '" + id + "' so discarding all !!!!!!!", span, Logger_1.Logger.parsecli(this));
                        this._receiveQueue = this._receiveQueue.filter(function (msg) { return msg.id !== id; });
                    }
                }
                const first = msgs[0];
                if (first.count === msgs.length) {
                    msgs.sort((a, b) => a.index - b.index);
                    if (msgs.length === 1) {
                        this._receiveQueue = this._receiveQueue.filter(function (msg) { return msg.id !== id; });
                        const singleresult = Message_1.Message.frommessage(first, first.data);
                        singleresult.priority = first.priority;
                        if (singleresult.command != "ping" && singleresult.command != "pong") {
                            singleresult.Process(this);
                        }
                    }
                    else {
                        let buffer = "";
                        msgs.forEach(msg => {
                            if (!openflow_api_1.NoderedUtil.IsNullUndefinded(msg.data)) {
                                buffer += msg.data;
                            }
                        });
                        this._receiveQueue = this._receiveQueue.filter(function (msg) { return msg.id !== id; });
                        const result = Message_1.Message.frommessage(first, buffer);
                        result.priority = first.priority;
                        if (result.command != "ping" && result.command != "pong") {
                            result.Process(this);
                        }
                    }
                }
            });
            this._sendQueue.forEach(msg => {
                let id = msg.id;
                try {
                    if (this._socketObject != null)
                        this._socketObject.send(JSON.stringify(msg));
                }
                catch (error) {
                    Logger_1.Logger.instanse.error(error, span, Logger_1.Logger.parsecli(this));
                }
                this._sendQueue = this._sendQueue.filter(function (msg) { return msg.id !== id; });
            });
        }
        catch (error) {
            Logger_1.Logger.instanse.error(error, span);
        }
        finally {
            span === null || span === void 0 ? void 0 : span.end();
        }
    }
    async Send(message, parent = null) {
        return new Promise(async (resolve, reject) => {
            this._Send(message, ((msg) => {
                if (!openflow_api_1.NoderedUtil.IsNullUndefinded(msg.error)) {
                    return reject(msg.error);
                }
                resolve(msg);
            }).bind(this), parent);
        });
    }
    _Send(message, cb, parent) {
        const messages = this.chunkString(message.data, Config_1.Config.websocket_package_size);
        if (openflow_api_1.NoderedUtil.IsNullUndefinded(messages) || messages.length === 0) {
            const singlemessage = SocketMessage_1.SocketMessage.frommessage(message, "", 1, 0);
            if (openflow_api_1.NoderedUtil.IsNullEmpty(message.replyto)) {
                this.messageQueue[singlemessage.id] = new openflow_api_1.QueuedMessage(singlemessage, cb);
            }
            this._sendQueue.push(singlemessage);
            return;
        }
        if (openflow_api_1.NoderedUtil.IsNullEmpty(message.id)) {
            message.id = openflow_api_1.NoderedUtil.GetUniqueIdentifier();
        }
        for (let i = 0; i < messages.length; i++) {
            const _message = SocketMessage_1.SocketMessage.frommessage(message, messages[i], messages.length, i);
            this._sendQueue.push(_message);
        }
        if (openflow_api_1.NoderedUtil.IsNullEmpty(message.replyto)) {
            this.messageQueue[message.id] = new openflow_api_1.QueuedMessage(message, cb);
        }
        this.ProcessQueue(parent);
    }
    chunkString(str, length) {
        if (openflow_api_1.NoderedUtil.IsNullEmpty(str)) {
            return null;
        }
        // tslint:disable-next-line: quotemark
        return str.match(new RegExp('.{1,' + length + '}', 'g'));
    }
    async Queue(data, queuename, options, span) {
        const d = JSON.parse(data);
        const q = new openflow_api_1.QueueMessage();
        if (this.clientversion == "1.0.80.0" || this.clientversion == "1.0.81.0" || this.clientversion == "1.0.82.0" || this.clientversion == "1.0.83.0" || this.clientversion == "1.0.84.0" || this.clientversion == "1.0.85.0") {
            q.data = d.payload;
        }
        else {
            q.data = d;
        }
        q.replyto = options.replyTo;
        q.error = d.error;
        q.correlationId = options.correlationId;
        q.queuename = queuename;
        q.consumerTag = options.consumerTag;
        q.routingkey = options.routingKey;
        q.exchangename = options.exchangename;
        let m = Message_1.Message.fromcommand("queuemessage");
        if (openflow_api_1.NoderedUtil.IsNullEmpty(q.correlationId)) {
            q.correlationId = m.id;
        }
        m.data = JSON.stringify(q);
        const q2 = await this.Send(m, span);
        if (q2.command == "error")
            throw new Error(q2.data);
        return q2.data;
    }
    async UnWatch(id, jwt) {
        if (this.watches[id]) {
            delete this.watches[id];
        }
    }
    async Watch(aggregates, collectionname, jwt, id = null) {
        if (typeof aggregates === "string") {
            try {
                aggregates = JSON.parse(aggregates);
            }
            catch (error) {
            }
        }
        // if (Array.isArray(aggregates)) {
        //     for (let p = 0; p < aggregates.length; p++) {
        //         let path = aggregates[p];
        //         if (typeof path === "string") {
        //             try {
        //                 path = JSON.parse(path);
        //             } catch (error) {
        //             }
        //         }
        //     }
        // }
        const stream = new clsstream();
        stream.id = openflow_api_1.NoderedUtil.GetUniqueIdentifier();
        stream.collectionname = collectionname;
        stream.aggregates = aggregates;
        if (id == null)
            id = openflow_api_1.NoderedUtil.GetUniqueIdentifier();
        this.watches[id] = {
            aggregates, collectionname //, streamid: stream.id
        };
        return id;
    }
}
exports.WebSocketServerClient = WebSocketServerClient;
class ClientWatch {
}
exports.ClientWatch = ClientWatch;
//# sourceMappingURL=WebSocketServerClient.js.map