"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
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 __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebSocketServerClient = exports.clsstream = void 0;
var SocketMessage_1 = require("./SocketMessage");
var Message_1 = require("./Messages/Message");
var Config_1 = require("./Config");
var amqpwrapper_1 = require("./amqpwrapper");
var openflow_api_1 = require("@openiap/openflow-api");
var WebSocketServer_1 = require("./WebSocketServer");
var Logger_1 = require("./Logger");
var WebServer_1 = require("./WebServer");
var Semaphore = function (n) { return ({
    n: n,
    down: function () {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!(this.n <= 0)) return [3 /*break*/, 2];
                        return [4 /*yield*/, this.wait()];
                    case 1:
                        _a.sent();
                        return [3 /*break*/, 0];
                    case 2:
                        this.n--;
                        return [2 /*return*/];
                }
            });
        });
    },
    up: function () {
        this.n++;
    },
    wait: function () {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!(this.n <= 0)) return [3 /*break*/, 2];
                        return [4 /*yield*/, new Promise(function (res, req) {
                                setImmediate(function () { return __awaiter(_this, void 0, void 0, function () { var _a; return __generator(this, function (_b) {
                                    switch (_b.label) {
                                        case 0:
                                            _a = res;
                                            return [4 /*yield*/, this.wait()];
                                        case 1: return [2 /*return*/, _a.apply(void 0, [_b.sent()])];
                                    }
                                }); }); });
                            })];
                    case 1: return [2 /*return*/, _a.sent()];
                    case 2: return [2 /*return*/];
                }
            });
        });
    },
}); };
var semaphore = Semaphore(1);
var clsstream = /** @class */ (function () {
    function clsstream() {
    }
    return clsstream;
}());
exports.clsstream = clsstream;
var WebSocketServerClient = /** @class */ (function () {
    function WebSocketServerClient(socketObject, req) {
        var _this = this;
        this.messageQueue = {};
        this.lastheartbeat = new Date();
        this.metrics = "";
        this.id = "";
        this._queues = [];
        this.devnull = false;
        this.commandcounter = {};
        this.streams = [];
        this.id = openflow_api_1.NoderedUtil.GetUniqueIdentifier();
        this._socketObject = socketObject;
        this._receiveQueue = [];
        this._sendQueue = [];
        var sock = (socketObject._socket);
        if (sock != undefined) {
            this.remoteip = sock.remoteAddress;
        }
        //if (NoderedUtil.IsNullEmpty(this.remoteip) && !NoderedUtil.IsNullUndefinded(req) && !NoderedUtil.IsNullUndefinded(req.headers)) {
        if (!openflow_api_1.NoderedUtil.IsNullUndefinded(req)) {
            this.remoteip = WebServer_1.WebServer.remoteip(req);
        }
        Logger_1.Logger.instanse.info("new client " + this.id + " from " + this.remoteip);
        socketObject.on("open", function (e) { return _this.open(e); });
        socketObject.on("message", function (e) { return _this.message(e); }); // e: MessageEvent
        socketObject.on("error", function (e) { return _this.error(e); });
        socketObject.on("close", function (e) { return _this.close(e); });
    }
    WebSocketServerClient.prototype.inccommandcounter = function (command) {
        var result = 0;
        if (!openflow_api_1.NoderedUtil.IsNullUndefinded(this.commandcounter[command]))
            result = this.commandcounter[command];
        result++;
        this.commandcounter[command] = result;
        return result;
    };
    WebSocketServerClient.prototype.open = function (e) {
        Logger_1.Logger.instanse.info("WebSocket connection opened " + e + " " + this.id);
    };
    WebSocketServerClient.prototype.close = function (e) {
        Logger_1.Logger.instanse.info("WebSocket connection closed " + e + " " + this.id + "/" + this.clientagent);
        this.Close();
    };
    WebSocketServerClient.prototype.error = function (e) {
        Logger_1.Logger.instanse.error("WebSocket error encountered " + e + " " + this.id + "/" + this.clientagent);
    };
    WebSocketServerClient.prototype.queuecount = function () {
        if (this._queues == null)
            return 0;
        return this._queues.length;
    };
    WebSocketServerClient.prototype.connected = function () {
        if (this._socketObject == null)
            return false;
        if (this._socketObject.readyState === this._socketObject.OPEN || this._socketObject.readyState === this._socketObject.CONNECTING) {
            return true;
        }
        if (this._socketObject.readyState === this._socketObject.CLOSED) {
            delete this._socketObject;
        }
        return false;
    };
    WebSocketServerClient.prototype.ping = function (parent) {
        var span = Logger_1.Logger.otel.startSubSpan("WebSocketServerClient.ping", parent);
        try {
            var msg = SocketMessage_1.SocketMessage.fromcommand("ping");
            if (this._socketObject == null) {
                if (this.queuecount() > 0) {
                    this.CloseConsumers(span);
                }
                if (this.streamcount() > 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;
            }
            this._socketObject.send(msg.tojson());
        }
        catch (error) {
            Logger_1.Logger.instanse.error(error);
            span.recordException(error);
            this._receiveQueue = [];
            this._sendQueue = [];
            try {
                if (this._socketObject != null) {
                    this.Close();
                }
            }
            catch (error) {
            }
        }
        finally {
            Logger_1.Logger.otel.endSpan(span);
        }
    };
    WebSocketServerClient.prototype._message = function (message) {
        //Logger.instanse.silly("WebSocket message received " + message);
        var msg = SocketMessage_1.SocketMessage.fromjson(message);
        Logger_1.Logger.instanse.silly("WebSocket message received id: " + msg.id + " index: " + msg.index + " count: " + msg.count);
        this._receiveQueue.push(msg);
        if ((msg.index + 1) >= msg.count)
            this.ProcessQueue();
    };
    WebSocketServerClient.prototype.message = function (message) {
        return __awaiter(this, void 0, void 0, function () {
            var username, errormessage;
            return __generator(this, function (_a) {
                username = "Unknown";
                try {
                    if (!openflow_api_1.NoderedUtil.IsNullUndefinded(this.user)) {
                        username = this.user.username;
                    }
                    this._message(message);
                }
                catch (error) {
                    Logger_1.Logger.instanse.error("[" + username + "/" + this.clientagent + "/" + this.id + "] WebSocket error encountered " + (error.message ? error.message : error));
                    errormessage = new Message_1.Message();
                    errormessage.command = "error";
                    errormessage.data = (error.message ? error.message : error);
                    this._socketObject.send(JSON.stringify(errormessage));
                }
                return [2 /*return*/];
            });
        });
    };
    WebSocketServerClient.prototype.CloseConsumers = function (parent) {
        return __awaiter(this, void 0, void 0, function () {
            var i, error_1;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, semaphore.down()];
                    case 1:
                        _a.sent();
                        i = this._queues.length - 1;
                        _a.label = 2;
                    case 2:
                        if (!(i >= 0)) return [3 /*break*/, 7];
                        _a.label = 3;
                    case 3:
                        _a.trys.push([3, 5, , 6]);
                        // await this.CloseConsumer(this._queues[i]);
                        return [4 /*yield*/, amqpwrapper_1.amqpwrapper.Instance().RemoveQueueConsumer(this._queues[i], undefined)];
                    case 4:
                        // await this.CloseConsumer(this._queues[i]);
                        _a.sent();
                        this._queues.splice(i, 1);
                        return [3 /*break*/, 6];
                    case 5:
                        error_1 = _a.sent();
                        Logger_1.Logger.instanse.error("WebSocketclient::closeconsumers " + error_1);
                        return [3 /*break*/, 6];
                    case 6:
                        i--;
                        return [3 /*break*/, 2];
                    case 7:
                        if (!openflow_api_1.NoderedUtil.IsNullUndefinded(WebSocketServer_1.WebSocketServer.websocket_queue_count))
                            WebSocketServer_1.WebSocketServer.websocket_queue_count.bind(__assign(__assign({}, Logger_1.Logger.otel.defaultlabels), { clientid: this.id })).update(this._queues.length);
                        semaphore.up();
                        return [2 /*return*/];
                }
            });
        });
    };
    WebSocketServerClient.prototype.Close = function () {
        return __awaiter(this, void 0, void 0, function () {
            var span, error_2;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        span = Logger_1.Logger.otel.startSpan("WebSocketServerClient.Close");
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 4, 5, 6]);
                        return [4 /*yield*/, this.CloseConsumers(span)];
                    case 2:
                        _a.sent();
                        return [4 /*yield*/, this.CloseStreams()];
                    case 3:
                        _a.sent();
                        if (this._socketObject != null) {
                            try {
                                this._socketObject.removeListener("open", function (e) { return _this.open(e); });
                                this._socketObject.removeListener("message", function (e) { return _this.message(e); }); // e: MessageEvent
                                this._socketObject.removeListener("error", function (e) { return _this.error(e); });
                                this._socketObject.removeListener("close", function (e) { return _this.close(e); });
                            }
                            catch (error) {
                                Logger_1.Logger.instanse.error("WebSocketclient::Close::removeListener " + error);
                            }
                            try {
                                this._socketObject.close();
                            }
                            catch (error) {
                                Logger_1.Logger.instanse.error("WebSocketclient::Close " + error);
                            }
                        }
                        return [3 /*break*/, 6];
                    case 4:
                        error_2 = _a.sent();
                        span.recordException(error_2);
                        throw error_2;
                    case 5:
                        WebSocketServer_1.WebSocketServer.update_mongodb_watch_count(this);
                        Logger_1.Logger.otel.endSpan(span);
                        return [7 /*endfinally*/];
                    case 6: return [2 /*return*/];
                }
            });
        });
    };
    WebSocketServerClient.prototype.CloseConsumer = function (queuename, parent) {
        return __awaiter(this, void 0, void 0, function () {
            var span, old, i, q, error_3, error_4;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        span = Logger_1.Logger.otel.startSubSpan("WebSocketServerClient.CloseConsumer", parent);
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 8, 9, 10]);
                        old = this._queues.length;
                        i = this._queues.length - 1;
                        _a.label = 2;
                    case 2:
                        if (!(i >= 0)) return [3 /*break*/, 7];
                        q = this._queues[i];
                        if (!(q && (q.queue == queuename || q.queuename == queuename))) return [3 /*break*/, 6];
                        _a.label = 3;
                    case 3:
                        _a.trys.push([3, 5, , 6]);
                        return [4 /*yield*/, amqpwrapper_1.amqpwrapper.Instance().RemoveQueueConsumer(this._queues[i], span)];
                    case 4:
                        _a.sent();
                        this._queues.splice(i, 1);
                        if (!openflow_api_1.NoderedUtil.IsNullUndefinded(WebSocketServer_1.WebSocketServer.websocket_queue_count))
                            WebSocketServer_1.WebSocketServer.websocket_queue_count.bind(__assign(__assign({}, Logger_1.Logger.otel.defaultlabels), { clientid: this.id })).update(this._queues.length);
                        return [3 /*break*/, 6];
                    case 5:
                        error_3 = _a.sent();
                        Logger_1.Logger.instanse.error("WebSocketclient::CloseConsumer " + error_3);
                        return [3 /*break*/, 6];
                    case 6:
                        i--;
                        return [3 /*break*/, 2];
                    case 7: return [3 /*break*/, 10];
                    case 8:
                        error_4 = _a.sent();
                        span.recordException(error_4);
                        throw error_4;
                    case 9:
                        Logger_1.Logger.otel.endSpan(span);
                        return [7 /*endfinally*/];
                    case 10: return [2 /*return*/];
                }
            });
        });
    };
    WebSocketServerClient.prototype.CreateConsumer = function (queuename, parent) {
        return __awaiter(this, void 0, void 0, function () {
            var span, autoDelete, qname_1, queue, AssertQueueOptions, error_5, error_6;
            var _this = this;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        span = Logger_1.Logger.otel.startSubSpan("WebSocketServerClient.CreateConsumer", parent);
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 7, 8, 9]);
                        autoDelete = false;
                        qname_1 = queuename;
                        if (openflow_api_1.NoderedUtil.IsNullEmpty(qname_1)) {
                            if (this.clientagent == "nodered") {
                                qname_1 = "nodered." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                                autoDelete = true;
                            }
                            else if (this.clientagent == "webapp") {
                                qname_1 = "webapp." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                                autoDelete = true;
                            }
                            else if (this.clientagent == "web") {
                                qname_1 = "web." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                                autoDelete = true;
                            }
                            else if (this.clientagent == "openrpa") {
                                qname_1 = "openrpa." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                                autoDelete = true;
                            }
                            else if (this.clientagent == "powershell") {
                                qname_1 = "powershell." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                                autoDelete = true;
                            }
                            else {
                                qname_1 = "unknown." + openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                                autoDelete = true;
                            }
                        }
                        return [4 /*yield*/, semaphore.down()];
                    case 2:
                        _a.sent();
                        this.CloseConsumer(qname_1, span);
                        queue = null;
                        _a.label = 3;
                    case 3:
                        _a.trys.push([3, 5, , 6]);
                        AssertQueueOptions = Object.assign({}, (amqpwrapper_1.amqpwrapper.Instance().AssertQueueOptions));
                        AssertQueueOptions.autoDelete = autoDelete;
                        return [4 /*yield*/, amqpwrapper_1.amqpwrapper.Instance().AddQueueConsumer(qname_1, AssertQueueOptions, this.jwt, function (msg, options, ack, done) { return __awaiter(_this, void 0, void 0, function () {
                                var _data, result, error_7;
                                return __generator(this, function (_a) {
                                    switch (_a.label) {
                                        case 0:
                                            _data = msg;
                                            _a.label = 1;
                                        case 1:
                                            _a.trys.push([1, 3, , 4]);
                                            return [4 /*yield*/, this.Queue(msg, qname_1, options)];
                                        case 2:
                                            result = _a.sent();
                                            ack();
                                            done(result);
                                            return [3 /*break*/, 4];
                                        case 3:
                                            error_7 = _a.sent();
                                            setTimeout(function () {
                                                ack(false);
                                                // ack(); // just eat the error 
                                                done(_data);
                                                console.error(qname_1 + " failed message queue message, nack and re queue message: ", (error_7.message ? error_7.message : error_7));
                                            }, Config_1.Config.amqp_requeue_time);
                                            return [3 /*break*/, 4];
                                        case 4: return [2 /*return*/];
                                    }
                                });
                            }); }, span)];
                    case 4:
                        queue = _a.sent();
                        if (queue) {
                            qname_1 = queue.queue;
                            this._queues.push(queue);
                        }
                        if (!openflow_api_1.NoderedUtil.IsNullUndefinded(WebSocketServer_1.WebSocketServer.websocket_queue_count))
                            WebSocketServer_1.WebSocketServer.websocket_queue_count.bind(__assign(__assign({}, Logger_1.Logger.otel.defaultlabels), { clientid: this.id })).update(this._queues.length);
                        return [3 /*break*/, 6];
                    case 5:
                        error_5 = _a.sent();
                        Logger_1.Logger.instanse.error("WebSocketclient::CreateConsumer " + error_5);
                        return [3 /*break*/, 6];
                    case 6:
                        semaphore.up();
                        if (queue != null)
                            return [2 /*return*/, queue.queue];
                        return [2 /*return*/, null];
                    case 7:
                        error_6 = _a.sent();
                        span.recordException(error_6);
                        throw error_6;
                    case 8:
                        Logger_1.Logger.otel.endSpan(span);
                        return [7 /*endfinally*/];
                    case 9: return [2 /*return*/];
                }
            });
        });
    };
    WebSocketServerClient.prototype.sleep = function (ms) {
        return new Promise(function (resolve) {
            setTimeout(resolve, ms);
        });
    };
    WebSocketServerClient.prototype.ProcessQueue = function () {
        var _this = this;
        if (this.devnull) {
            this._receiveQueue = [];
            this._sendQueue = [];
            return;
        }
        var username = "Unknown";
        if (!openflow_api_1.NoderedUtil.IsNullUndefinded(this.user)) {
            username = this.user.username;
        }
        var ids = [];
        this._receiveQueue.forEach(function (msg) {
            if (ids.indexOf(msg.id) === -1) {
                ids.push(msg.id);
            }
        });
        ids.forEach(function (id) {
            var 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("[" + username + "/" + _this.clientagent + "/" + _this.id + "] _receiveQueue containers more than " + Config_1.Config.websocket_max_package_count + " messages for id '" + id + "', disconnecting");
                    _this.Close();
                }
                else {
                    Logger_1.Logger.instanse.error("[" + username + "/" + _this.clientagent + "/" + _this.id + "] _receiveQueue containers more than " + Config_1.Config.websocket_max_package_count + " messages for id '" + id + "' so discarding all !!!!!!!");
                    _this._receiveQueue = _this._receiveQueue.filter(function (msg) { return msg.id !== id; });
                }
            }
            var first = msgs[0];
            if (first.count === msgs.length) {
                msgs.sort(function (a, b) { return a.index - b.index; });
                if (msgs.length === 1) {
                    _this._receiveQueue = _this._receiveQueue.filter(function (msg) { return msg.id !== id; });
                    var singleresult = Message_1.Message.frommessage(first, first.data);
                    singleresult.Process(_this);
                }
                else {
                    var buffer_1 = "";
                    msgs.forEach(function (msg) {
                        if (!openflow_api_1.NoderedUtil.IsNullUndefinded(msg.data)) {
                            buffer_1 += msg.data;
                        }
                    });
                    _this._receiveQueue = _this._receiveQueue.filter(function (msg) { return msg.id !== id; });
                    var result = Message_1.Message.frommessage(first, buffer_1);
                    result.Process(_this);
                }
            }
            else {
                // Logger.instanse.debug("[" + username + "] WebSocketclient::ProcessQueue receiveQueue: Cannot process i have " + msgs.length + " out of " + first.count + " for message " + first.id);
            }
        });
        this._sendQueue.forEach(function (msg) {
            var id = msg.id;
            try {
                _this._socketObject.send(JSON.stringify(msg));
            }
            catch (error) {
                Logger_1.Logger.instanse.error("WebSocket error encountered " + error);
            }
            _this._sendQueue = _this._sendQueue.filter(function (msg) { return msg.id !== id; });
        });
        // if (this._receiveQueue.length > 25 || this._sendQueue.length > 25) {
        //     Logger.instanse.debug("[" + username + "] WebSocketclient::ProcessQueue receiveQueue: " + this._receiveQueue.length + " sendQueue: " + this._sendQueue.length);
        // }
    };
    WebSocketServerClient.prototype.Send = function (message) {
        return __awaiter(this, void 0, void 0, function () {
            var _this = this;
            return __generator(this, function (_a) {
                return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
                        return __generator(this, function (_a) {
                            this._Send(message, (function (msg) {
                                if (!openflow_api_1.NoderedUtil.IsNullUndefinded(msg.error)) {
                                    return reject(msg.error);
                                }
                                resolve(msg);
                            }).bind(this));
                            return [2 /*return*/];
                        });
                    }); })];
            });
        });
    };
    WebSocketServerClient.prototype._Send = function (message, cb) {
        var messages = this.chunkString(message.data, Config_1.Config.websocket_package_size);
        if (openflow_api_1.NoderedUtil.IsNullUndefinded(messages) || messages.length === 0) {
            var 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);
                WebSocketServer_1.WebSocketServer.update_message_queue_count(this);
            }
            this._sendQueue.push(singlemessage);
            return;
        }
        if (openflow_api_1.NoderedUtil.IsNullEmpty(message.id)) {
            message.id = openflow_api_1.NoderedUtil.GetUniqueIdentifier();
        }
        for (var i = 0; i < messages.length; i++) {
            var _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);
            WebSocketServer_1.WebSocketServer.update_message_queue_count(this);
        }
        // setTimeout(() => {
        //     this.ProcessQueue();
        // }, 500);
        this.ProcessQueue();
    };
    WebSocketServerClient.prototype.chunkString = function (str, length) {
        if (openflow_api_1.NoderedUtil.IsNullEmpty(str)) {
            return null;
        }
        // tslint:disable-next-line: quotemark
        return str.match(new RegExp('.{1,' + length + '}', 'g'));
    };
    WebSocketServerClient.prototype.Queue = function (data, queuename, options) {
        return __awaiter(this, void 0, void 0, function () {
            var d, q, m, q2;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        d = JSON.parse(data);
                        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.data = d.payload; 
                        q.replyto = options.replyTo;
                        q.error = d.error;
                        q.correlationId = options.correlationId;
                        q.queuename = queuename;
                        q.consumerTag = options.consumerTag;
                        q.routingkey = options.routingkey;
                        q.exchange = options.exchange;
                        m = Message_1.Message.fromcommand("queuemessage");
                        if (openflow_api_1.NoderedUtil.IsNullEmpty(q.correlationId)) {
                            q.correlationId = m.id;
                        }
                        m.data = JSON.stringify(q);
                        return [4 /*yield*/, this.Send(m)];
                    case 1:
                        q2 = _a.sent();
                        if (q2.command == "error")
                            throw new Error(q2.data);
                        return [2 /*return*/, q2.data];
                }
            });
        });
    };
    WebSocketServerClient.prototype.Query = function (collection, query, projection, orderby, top, skip) {
        if (projection === void 0) { projection = null; }
        if (orderby === void 0) { orderby = { _created: -1 }; }
        if (top === void 0) { top = 500; }
        if (skip === void 0) { skip = 0; }
        return __awaiter(this, void 0, void 0, function () {
            var q, msg, q2;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        q = new openflow_api_1.QueryMessage();
                        q.collectionname = collection;
                        q.query = query;
                        q.projection = projection;
                        q.orderby = orderby;
                        q.top = top;
                        q.skip = skip;
                        msg = new Message_1.Message();
                        msg.command = "query";
                        msg.data = JSON.stringify(q);
                        return [4 /*yield*/, this.Send(msg)];
                    case 1:
                        q2 = _a.sent();
                        return [2 /*return*/, q2.result];
                }
            });
        });
    };
    WebSocketServerClient.prototype.MapReduce = function (collection, map, reduce, finalize, query, out, scope) {
        return __awaiter(this, void 0, void 0, function () {
            var q, msg, q2;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        q = new openflow_api_1.MapReduceMessage(map, reduce, finalize, query, out);
                        q.collectionname = collection;
                        q.scope = scope;
                        msg = new Message_1.Message();
                        msg.command = "mapreduce";
                        q.out = out;
                        msg.data = Message_1.JSONfn.stringify(q);
                        return [4 /*yield*/, this.Send(msg)];
                    case 1:
                        q2 = _a.sent();
                        return [2 /*return*/, q2.result];
                }
            });
        });
    };
    WebSocketServerClient.prototype.Insert = function (collection, model) {
        return __awaiter(this, void 0, void 0, function () {
            var q, msg, q2;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        q = new openflow_api_1.InsertOneMessage();
                        q.collectionname = collection;
                        q.item = model;
                        msg = new Message_1.Message();
                        msg.command = "insertone";
                        msg.data = Message_1.JSONfn.stringify(q);
                        return [4 /*yield*/, this.Send(msg)];
                    case 1:
                        q2 = _a.sent();
                        return [2 /*return*/, q2.result];
                }
            });
        });
    };
    WebSocketServerClient.prototype.Update = function (collection, model) {
        return __awaiter(this, void 0, void 0, function () {
            var q, msg, q2;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        q = new openflow_api_1.UpdateOneMessage();
                        q.collectionname = collection;
                        q.item = model;
                        msg = new Message_1.Message();
                        msg.command = "updateone";
                        msg.data = Message_1.JSONfn.stringify(q);
                        return [4 /*yield*/, this.Send(msg)];
                    case 1:
                        q2 = _a.sent();
                        return [2 /*return*/, q2.result];
                }
            });
        });
    };
    WebSocketServerClient.prototype.UpdateMany = function (collection, query, document) {
        return __awaiter(this, void 0, void 0, function () {
            var q, msg, q2;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        q = new openflow_api_1.UpdateManyMessage();
                        q.collectionname = collection;
                        q.item = document;
                        q.query = query;
                        msg = new Message_1.Message();
                        msg.command = "updateone";
                        msg.data = Message_1.JSONfn.stringify(q);
                        return [4 /*yield*/, this.Send(msg)];
                    case 1:
                        q2 = _a.sent();
                        return [2 /*return*/, q2.result];
                }
            });
        });
    };
    WebSocketServerClient.prototype.Delete = function (collection, id) {
        return __awaiter(this, void 0, void 0, function () {
            var q, msg;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        q = new openflow_api_1.DeleteOneMessage();
                        q.collectionname = collection;
                        q._id = id;
                        msg = new Message_1.Message();
                        msg.command = "deleteone";
                        msg.data = JSON.stringify(q);
                        return [4 /*yield*/, this.Send(msg)];
                    case 1:
                        _a.sent();
                        return [2 /*return*/];
                }
            });
        });
    };
    WebSocketServerClient.prototype.streamcount = function () {
        if (this.streams == null)
            return 0;
        return this.streams.length;
    };
    WebSocketServerClient.prototype.CloseStreams = function () {
        return __awaiter(this, void 0, void 0, function () {
            var i, error_8;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!(this.streams != null && this.streams.length > 0)) return [3 /*break*/, 7];
                        i = this.streams.length - 1;
                        _a.label = 1;
                    case 1:
                        if (!(i >= 0)) return [3 /*break*/, 7];
                        _a.label = 2;
                    case 2:
                        _a.trys.push([2, 5, , 6]);
                        if (!(this.streams[i] != null && this.streams[i].stream != null && !this.streams[i].stream.isClosed())) return [3 /*break*/, 4];
                        return [4 /*yield*/, this.streams[i].stream.close()];
                    case 3:
                        _a.sent();
                        _a.label = 4;
                    case 4:
                        this.streams.splice(i, 1);
                        return [3 /*break*/, 6];
                    case 5:
                        error_8 = _a.sent();
                        Logger_1.Logger.instanse.error("WebSocketclient::CloseStreams " + error_8 + " " + this.id + "/" + this.clientagent);
                        return [3 /*break*/, 6];
                    case 6:
                        i--;
                        return [3 /*break*/, 1];
                    case 7: return [2 /*return*/];
                }
            });
        });
    };
    WebSocketServerClient.prototype.CloseStream = function (id) {
        return __awaiter(this, void 0, void 0, function () {
            var i, error_9;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        if (!(this.streams != null && this.streams.length > 0)) return [3 /*break*/, 8];
                        i = this.streams.length - 1;
                        _a.label = 1;
                    case 1:
                        if (!(i >= 0)) return [3 /*break*/, 8];
                        _a.label = 2;
                    case 2:
                        _a.trys.push([2, 6, , 7]);
                        if (!(this.streams[i] != null && this.streams[i].id == id)) return [3 /*break*/, 5];
                        if (!!this.streams[i].stream.isClosed()) return [3 /*break*/, 4];
                        return [4 /*yield*/, this.streams[i].stream.close()];
                    case 3:
                        _a.sent();
                        _a.label = 4;
                    case 4:
                        this.streams.splice(i, 1);
                        _a.label = 5;
                    case 5: return [3 /*break*/, 7];
                    case 6:
                        error_9 = _a.sent();
                        Logger_1.Logger.instanse.error("WebSocketclient::CloseStream " + error_9 + " " + this.id + "/" + this.clientagent);
                        return [3 /*break*/, 7];
                    case 7:
                        i--;
                        return [3 /*break*/, 1];
                    case 8:
                        WebSocketServer_1.WebSocketServer.update_mongodb_watch_count(this);
                        return [2 /*return*/];
                }
            });
        });
    };
    WebSocketServerClient.prototype.UnWatch = function (id, jwt) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                this.CloseStream(id);
                return [2 /*return*/];
            });
        });
    };
    WebSocketServerClient.prototype.Watch = function (aggregates, collectionname, jwt) {
        return __awaiter(this, void 0, void 0, function () {
            var stream, _a, options, me;
            var _this = this;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        stream = new clsstream();
                        stream.id = openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                        _a = stream;
                        return [4 /*yield*/, Config_1.Config.db.watch(aggregates, collectionname, jwt)];
                    case 1:
                        _a.stream = _b.sent();
                        this.streams.push(stream);
                        options = { fullDocument: "updateLookup" };
                        me = this;
                        try {
                            stream.stream.on("error", function (err) {
                                console.error(err);
                            });
                            stream.stream.on("change", function (next) {
                                try {
                                    // Logger.instanse.info(JSON.stringify(next, null, 4));
                                    Logger_1.Logger.instanse.info("Watch: " + JSON.stringify(next.documentKey));
                                    var msg = SocketMessage_1.SocketMessage.fromcommand("watchevent");
                                    var q = new openflow_api_1.WatchEventMessage();
                                    q.id = stream.id;
                                    q.result = next;
                                    if (q.result && q.result.fullDocument) {
                                        q.result.fullDocument = Config_1.Config.db.decryptentity(q.result.fullDocument);
                                    }
                                    msg.data = JSON.stringify(q);
                                    me._socketObject.send(msg.tojson());
                                }
                                catch (error) {
                                    Logger_1.Logger.instanse.error("WebSocketclient::Watch::changeListener " + error + " " + _this.id + "/" + _this.clientagent);
                                }
                            }, options);
                            WebSocketServer_1.WebSocketServer.update_mongodb_watch_count(this);
                            return [2 /*return*/, stream.id];
                        }
                        catch (error) {
                            Logger_1.Logger.instanse.error("WebSocketclient::Watch " + error + " " + this.id + "/" + this.clientagent);
                            throw error;
                        }
                        return [2 /*return*/];
                }
            });
        });
    };
    return WebSocketServerClient;
}());
exports.WebSocketServerClient = WebSocketServerClient;
//# sourceMappingURL=WebSocketServerClient.js.map