"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueueClient = void 0;
const openflow_api_1 = require("@openiap/openflow-api");
const amqpwrapper_1 = require("./amqpwrapper");
const Config_1 = require("./Config");
const Crypt_1 = require("./Crypt");
const Logger_1 = require("./Logger");
const Message_1 = require("./Messages/Message");
class QueueClient {
    static async configure(parent) {
        const span = Logger_1.Logger.otel.startSubSpan("QueueClient.configure", parent);
        try {
            await QueueClient.connect();
            var instance = amqpwrapper_1.amqpwrapper.Instance();
            instance.on("connected", () => {
                QueueClient.connect();
            });
        }
        catch (error) {
            Logger_1.Logger.instanse.error(error, span);
            throw error;
        }
        finally {
            Logger_1.Logger.otel.endSpan(span);
        }
    }
    static async connect() {
        await this.RegisterMyQueue();
        await this.RegisterOpenflowQueue();
    }
    static async RegisterOpenflowQueue() {
        const AssertQueueOptions = Object.assign({}, (amqpwrapper_1.amqpwrapper.Instance().AssertQueueOptions));
        AssertQueueOptions.exclusive = false;
        AssertQueueOptions["x-max-priority"] = 5;
        AssertQueueOptions.maxPriority = 5;
        await amqpwrapper_1.amqpwrapper.Instance().AddQueueConsumer(Crypt_1.Crypt.rootUser(), this.queuename, AssertQueueOptions, null, async (data, options, ack, done) => {
            const msg = Message_1.Message.fromjson(data);
            let span = null;
            if (!Config_1.Config.db.isConnected) {
                ack(false);
                return;
            }
            try {
                msg.priority = options.priority;
                if (!openflow_api_1.NoderedUtil.IsNullEmpty(options.replyTo)) {
                    span = Logger_1.Logger.otel.startSpan("OpenFlow Queue Process Message", msg.traceId, msg.spanId);
                    Logger_1.Logger.instanse.debug("Process command: " + msg.command + " id: " + msg.id + " correlationId: " + options.correlationId, span);
                    await msg.QueueProcess(options, span);
                    ack();
                    await amqpwrapper_1.amqpwrapper.Instance().send(options.exchangename, options.replyTo, msg, Config_1.Config.openflow_amqp_expiration, options.correlationId, options.routingKey, span);
                }
                else {
                    ack(false);
                    Logger_1.Logger.instanse.debug("[queue][ack] No replyto !!!!", span);
                }
            }
            catch (error) {
                try {
                    ack(false);
                }
                catch (error) {
                }
            }
            finally {
                Logger_1.Logger.otel.endSpan(span);
            }
        }, null);
    }
    static async RegisterMyQueue() {
        const AssertQueueOptions = Object.assign({}, (amqpwrapper_1.amqpwrapper.Instance().AssertQueueOptions));
        AssertQueueOptions.exclusive = false;
        this.queue = await amqpwrapper_1.amqpwrapper.Instance().AddQueueConsumer(Crypt_1.Crypt.rootUser(), "", AssertQueueOptions, null, async (data, options, ack, done) => {
            const msg = Message_1.Message.fromjson(data);
            try {
                if (openflow_api_1.NoderedUtil.IsNullEmpty(options.replyTo)) {
                    ack();
                    const exists = this.messages.filter(x => x.correlationId == options.correlationId);
                    if (exists.length > 0) {
                        Logger_1.Logger.instanse.silly("[queue][ack] Received response for command: " + msg.command + " queuename: " + this.queuename + " replyto: " + options.replyTo + " correlationId: " + options.correlationId, null);
                        this.messages = this.messages.filter(x => x.correlationId != options.correlationId);
                        exists[0].cb(msg);
                    }
                    else {
                        // throw new Error("Failed locating receiving message");
                    }
                }
                else {
                    ack(false);
                }
            }
            catch (error) {
                ack(false);
            }
        }, null);
    }
    static async SendForProcessing(msg, priority, span) {
        return new Promise(async (resolve, reject) => {
            try {
                msg.correlationId = openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                this.messages.push(msg);
                Logger_1.Logger.instanse.debug("Submit command: " + msg.command + " id: " + msg.id + " correlationId: " + msg.correlationId, span);
                msg.cb = (result) => {
                    if (result.replyto != msg.id) {
                        Logger_1.Logger.instanse.warn("Received response failed for command: " + msg.command + " id: " + result.id + " replyto: " + result.replyto + " but expected reply to be " + msg.id + " correlationId: " + result.correlationId, span);
                        result.id = openflow_api_1.NoderedUtil.GetUniqueIdentifier();
                        result.replyto = msg.id;
                    }
                    result.correlationId = msg.correlationId;
                    Logger_1.Logger.instanse.debug("Got reply command: " + msg.command + " id: " + result.id + " replyto: " + result.replyto + " correlationId: " + result.correlationId, span);
                    resolve(result);
                };
                Logger_1.Logger.instanse.silly("Submit request for command: " + msg.command + " queuename: " + this.queuename + " replyto: " + this.queue.queue + " correlationId: " + msg.correlationId, null);
                await amqpwrapper_1.amqpwrapper.Instance().sendWithReplyTo("", this.queuename, this.queue.queue, JSON.stringify(msg), Config_1.Config.openflow_amqp_expiration, msg.correlationId, "", span, priority);
            }
            catch (error) {
                if (openflow_api_1.NoderedUtil.IsNullUndefinded(this.queue)) {
                    Logger_1.Logger.instanse.warn("SendForProcessing queue is null, shutdown amqp connection", span);
                    process.exit(406);
                    // amqpwrapper.Instance().shutdown();
                    // amqpwrapper.Instance().connect(null);
                }
                else {
                    Logger_1.Logger.instanse.error(error, span);
                }
                reject(error);
            }
        });
    }
}
exports.QueueClient = QueueClient;
QueueClient.queue = null;
QueueClient.queuename = "openflow";
QueueClient.messages = [];
//# sourceMappingURL=QueueClient.js.map