"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 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(socketObject, req) {
        this.messageQueue = {};
        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._amqpdisconnected = null;
        this._dbdisconnected = null;
        this._dbconnected = null;
        this.watches = {};
        this.id = openflow_api_1.NoderedUtil.GetUniqueIdentifier();
        this._socketObject = socketObject;
        this._receiveQueue = [];
        this._sendQueue = [];
        const 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 = WebSocketServerClient.remoteip(req);
        }
        Logger_1.Logger.instanse.debug("WebSocketServerClient", "constructor", "new client " + this.id + " from " + this.remoteip);
        socketObject.on("open", this.open.bind(this));
        socketObject.on("message", this.message.bind(this)); // e: MessageEvent
        socketObject.on("error", this.error.bind(this));
        socketObject.on("close", this.close.bind(this));
        this._dbdisconnected = this.dbdisconnected.bind(this);
        this._dbconnected = this.dbconnected.bind(this);
        Config_1.Config.db.on("disconnected", this._dbdisconnected);
        Config_1.Config.db.on("connected", this._dbconnected);
        this._amqpdisconnected = this.amqpdisconnected.bind(this);
        amqpwrapper_1.amqpwrapper.Instance().on("disconnected", this._amqpdisconnected);
    }
    static remoteip(req) {
        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 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("WebSocketServerClient", "amqpdisconnected", "Send queue closed message to " + this.id + " for queue " + q.queuename);
        }
        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("WebSocketServerClient", "amqpdisconnected", "Send queue closed message to " + this.id + " for exchange " + q.exchangename);
        }
        this._exchanges = [];
        this.CloseConsumers(null);
    }
    open(e) {
        Logger_1.Logger.instanse.debug("WebSocketServerClient", "open", "Connection opened " + e + " " + this.id);
    }
    close(e) {
        Logger_1.Logger.instanse.debug("WebSocketServerClient", "close", "Connection closed " + e + " " + this.id + "/" + this.clientagent);
        this.Close();
        Config_1.Config.db.removeListener("disconnected", this._dbdisconnected);
        Config_1.Config.db.removeListener("connected", this._dbconnected);
    }
    error(e) {
        Logger_1.Logger.instanse.error("WebSocketServerClient", "error", e + " " + this.id + "/" + this.clientagent);
    }
    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;
        }
        if (this._socketObject.readyState === this._socketObject.CLOSED) {
            delete this._socketObject;
        }
        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("WebSocketServerClient", "ping", error);
            span === null || span === void 0 ? void 0 : span.recordException(error);
            this._receiveQueue = [];
            this._sendQueue = [];
            if (this._socketObject != null) {
                this.Close().catch((err) => {
                    Logger_1.Logger.instanse.error("WebSocketServerClient", "ping", error);
                });
            }
        }
        finally {
            Logger_1.Logger.otel.endSpan(span);
        }
    }
    _message(message) {
        Logger_1.Logger.instanse.silly("WebSocketServerClient", "_message", "WebSocket message received " + message);
        let msg = SocketMessage_1.SocketMessage.fromjson(message);
        Logger_1.Logger.instanse.silly("WebSocketServerClient", "_message", "WebSocket message received id: " + msg.id + " index: " + msg.index + " count: " + msg.count);
        this._receiveQueue.push(msg);
        if ((msg.index + 1) >= msg.count)
            this.ProcessQueue();
    }
    async message(message) {
        let 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("WebSocketServerClient", "message", "[" + username + "/" + this.clientagent + "/" + this.id + "] " + (error.message ? error.message : error));
            const errormessage = new Message_1.Message();
            errormessage.command = "error";
            errormessage.data = (error.message ? error.message : error);
            this._socketObject.send(JSON.stringify(errormessage));
        }
    }
    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("WebSocketServerClient", "CloseConsumers", "WebSocketclient::closeconsumers " + error);
            }
        }
        semaphore.up();
    }
    async Close() {
        const span = Logger_1.Logger.otel.startSpan("WebSocketServerClient.Close");
        try {
            Config_1.Config.db.removeListener("disconnected", this._dbdisconnected);
            Config_1.Config.db.removeListener("connected", this._dbconnected);
            await this.CloseConsumers(span);
            // await this.CloseStreams();
            if (this._socketObject != null) {
                try {
                    this._socketObject.removeAllListeners();
                }
                catch (error) {
                    Logger_1.Logger.instanse.error("WebSocketServerClient", "Close", error);
                }
                try {
                    this._socketObject.close();
                }
                catch (error) {
                    Logger_1.Logger.instanse.error("WebSocketServerClient", "Close", error);
                }
            }
            try {
                amqpwrapper_1.amqpwrapper.Instance().removeListener("disconnected", this._amqpdisconnected);
            }
            catch (error) {
                Logger_1.Logger.instanse.error("WebSocketServerClient", "Close", error);
            }
            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]];
            }
            // this._receiveQueue
            // this._sendQueue
            // this._queues
            // this._exchanges
        }
        catch (error) {
            span === null || span === void 0 ? void 0 : span.recordException(error);
            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("WebSocketServerClient", "CloseConsumer", err);
                        });
                        this._queues.splice(i, 1);
                        this._queuescurrent--;
                        this._queuescurrentstr = this._queuescurrent.toString();
                    }
                    catch (error) {
                        Logger_1.Logger.instanse.error("WebSocketServerClient", "CloseConsumer", error);
                    }
                }
            }
        }
        catch (error) {
            span === null || span === void 0 ? void 0 : span.recordException(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) => {
                    const _data = msg;
                    try {
                        const result = await this.Queue(msg, exchange, options);
                        done(result);
                        ack();
                    }
                    catch (error) {
                        setTimeout(() => {
                            ack(false);
                            Logger_1.Logger.instanse.error("WebSocketServerClient", "RegisterExchange", exchange + " failed message queue message, nack and re queue message: ");
                            Logger_1.Logger.instanse.error("WebSocketServerClient", "RegisterExchange", error);
                        }, Config_1.Config.amqp_requeue_time);
                    }
                }, 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("WebSocketServerClient", "RegisterExchange", error);
            }
            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) {
            span === null || span === void 0 ? void 0 : span.recordException(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("WebSocketServerClient", "CreateConsumer", qname + " already exists, removing before re-creating");
                    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;
                    var _data = msg;
                    try {
                        Logger_1.Logger.instanse.verbose("WebSocketServerClient", "CreateConsumer", "[preack] queuename: " + queuename + " qname: " + qname + " replyto: " + options.replyTo + " correlationId: " + options.correlationId);
                        _data = await this.Queue(msg, qname, options);
                        ;
                        ack();
                        // const result = await this.Queue(msg, qname, options);
                        // done(result);
                        Logger_1.Logger.instanse.debug("WebSocketServerClient", "CreateConsumer", "[ack] queuename: " + queuename + " qname: " + qname + " replyto: " + options.replyTo + " correlationId: " + options.correlationId);
                    }
                    catch (error) {
                        setTimeout(() => {
                            ack(false);
                            Logger_1.Logger.instanse.warn("WebSocketServerClient", "CreateConsumer", "[nack] queuename: " + queuename + " qname: " + qname + " replyto: " + options.replyTo + " correlationId: " + options.correlationId + " error: " + (error.message ? error.message : error));
                        }, Config_1.Config.amqp_requeue_time);
                    }
                    finally {
                        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) {
            span === null || span === void 0 ? void 0 : span.recordException(error);
            throw error;
        }
        finally {
            Logger_1.Logger.otel.endSpan(span);
        }
    }
    sleep(ms) {
        return new Promise(resolve => {
            setTimeout(resolve, ms);
        });
    }
    ProcessQueue() {
        if (this.devnull) {
            this._receiveQueue = [];
            this._sendQueue = [];
            return;
        }
        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("WebSocketServerClient", "ProcessQueue", "[" + 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("WebSocketServerClient", "ProcessQueue", "[" + 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; });
                }
            }
            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;
                    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;
                    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("WebSocketServerClient", "ProcessQueue", error);
            }
            this._sendQueue = this._sendQueue.filter(function (msg) { return msg.id !== id; });
        });
    }
    async Send(message) {
        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));
        });
    }
    _Send(message, cb) {
        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();
    }
    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) {
        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);
        if (q2.command == "error")
            throw new Error(q2.data);
        return q2.data;
    }
    async Query(collection, query, projection = null, orderby = { _created: -1 }, top = 500, skip = 0) {
        const q = new openflow_api_1.QueryMessage();
        q.collectionname = collection;
        q.query = query;
        q.projection = projection;
        q.orderby = orderby;
        q.top = top;
        q.skip = skip;
        const msg = new Message_1.Message();
        msg.command = "query";
        msg.data = JSON.stringify(q);
        const q2 = await this.Send(msg);
        return q2.result;
    }
    async MapReduce(collection, map, reduce, finalize, query, out, scope) {
        const q = new openflow_api_1.MapReduceMessage(map, reduce, finalize, query, out);
        q.collectionname = collection;
        q.scope = scope;
        const msg = new Message_1.Message();
        msg.command = "mapreduce";
        q.out = out;
        msg.data = Message_1.JSONfn.stringify(q);
        const q2 = await this.Send(msg);
        return q2.result;
    }
    async Insert(collection, model) {
        const q = new openflow_api_1.InsertOneMessage();
        q.collectionname = collection;
        q.item = model;
        const msg = new Message_1.Message();
        msg.command = "insertone";
        msg.data = Message_1.JSONfn.stringify(q);
        const q2 = await this.Send(msg);
        return q2.result;
    }
    async Update(collection, model) {
        const q = new openflow_api_1.UpdateOneMessage();
        q.collectionname = collection;
        q.item = model;
        const msg = new Message_1.Message();
        msg.command = "updateone";
        msg.data = Message_1.JSONfn.stringify(q);
        const q2 = await this.Send(msg);
        return q2.result;
    }
    async UpdateMany(collection, query, document) {
        const q = new openflow_api_1.UpdateManyMessage();
        q.collectionname = collection;
        q.item = document;
        q.query = query;
        const msg = new Message_1.Message();
        msg.command = "updateone";
        msg.data = Message_1.JSONfn.stringify(q);
        const q2 = await this.Send(msg);
        return q2.result;
    }
    async Delete(collection, id) {
        const q = new openflow_api_1.DeleteOneMessage();
        q.collectionname = collection;
        q.id = id;
        const msg = new Message_1.Message();
        msg.command = "deleteone";
        msg.data = JSON.stringify(q);
        await this.Send(msg);
    }
    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