"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LrpWatcher = void 0;
const tslib_1 = require("tslib");
const inversify_1 = require("inversify");
const listr2_1 = require("listr2");
const codiac_common_1 = require("@codiac.io/codiac-common");
// import { AsyncAck, CommChannelRef, OperationCompletionCodeEnum, OperationStateEnum, OperationStatus } from '../apis/codiac-relay/contracts';
const message_contracts_1 = require("../message-contracts");
const lrp_watcher_utils_1 = require("./lrp-watcher-utils");
/** Triggers and renders real time status for Long Running Processes.
 *
 * That is, it fires an async request to trigger the process,
 * then monitors a socket for real time status messages,
 * and renders them in sequential order.
 */
let LrpWatcher = class LrpWatcher {
    constructor(msgClient, logger) {
        this.msgClient = msgClient;
        this.logger = logger;
    }
    // private setStatusHandlers(): void {
    //   // this.spinners["operationStatus"] = ora("Cluster create interim status: ").start();
    //   this.statusHandlerId = this.relayWebSocket.listenFor("operationStatus", msg => {
    //     // this._ui.userMessage(`Cluster create interim status: ${JSON.stringify(msg.payload)}`);
    //     // this.spinners?.add({
    //     //   title: "interim from relay",
    //     //   task: async (ctx, task): Promise<void> => {
    //     //     task.output = "payload: ".concat(JSON.stringify(msg.payload));
    //     //   }
    //     //   // , rendererOptions: { outputBar: 1 }
    //     // });
    //   });
    //   // this.completionHandlerId = this.relayWebSocket.listenFor("clusterCreateCompleted", msg => {
    //   //   this.isCompleted = true;
    //   //   // this.spinners["operationStatus"].succeed().suffixText = "Complete!";
    //   //   this._ui.userMessage(`Cluster create completed ${JSON.stringify(msg.payload)}`);
    //   //   this.removeStatusListeners();
    //   // });
    // }
    removeStatusListeners() {
        let closed = false;
        if (this.msgClient) {
            closed = closed && this.msgClient.unsubscribe(lrp_watcher_utils_1.LrpWatcherUtils.STATUS_MSG_TYPE, { subscriptionId: this.statusHandlerId });
            // closed = closed && this.relayWebSocket.unlisten("clusterCreateCompleted", this.completionHandlerId!);
        }
        return closed;
    }
    /** Opens and closes its own web socket.
     * Throws any errors.
     * Renders all real time status messages as logs off the main operation.
     */
    triggerAndWatch(mainOpCode, opIngTitle, trigger) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let spinners = new listr2_1.Listr({
                title: opIngTitle,
                rendererOptions: { outputBar: Infinity, persistentOutput: true, timer: listr2_1.PRESET_TIMER },
                task: (ctx, task) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                    return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
                        // 1. open real time status stream
                        let commChannel;
                        commChannel = {
                            socketId: yield this.msgClient.connect() // .start()
                        };
                        // this.setStatusHandlers();
                        this.statusHandlerId = this.msgClient.subscribe(lrp_watcher_utils_1.LrpWatcherUtils.STATUS_MSG_TYPE, (err, msg, meta, raw) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                            var _l, _m, _o, _p, _q, _r;
                            if (msg) {
                                let statusMsg = msg;
                                // COMPLETION STATUS
                                if (statusMsg.opCode == mainOpCode && statusMsg.state == message_contracts_1.OperationStateEnum.Completed) {
                                    task.output = "".concat((_m = (_l = statusMsg.completionCode) !== null && _l !== void 0 ? _l : statusMsg.message) !== null && _m !== void 0 ? _m : statusMsg.state, "!");
                                    task.title = task.title.concat("...", (_o = statusMsg.completionCode) !== null && _o !== void 0 ? _o : statusMsg.state);
                                    task.task.complete();
                                    ctx.res = lrp_watcher_utils_1.LrpWatcherUtils.resultFromStatusMessage(statusMsg);
                                    // Poor man's DRAIN
                                    // TODO: drain the socket messages and the Listr tasks before we close up shop
                                    setTimeout(() => {
                                        this.removeStatusListeners();
                                        if (result.error) {
                                            reject(result.error);
                                        }
                                        else {
                                            resolve();
                                        }
                                    }, 1000);
                                }
                                else {
                                    if (statusMsg.state == message_contracts_1.OperationStateEnum.Completed) {
                                        task.output = statusMsg.opIngTitle.concat("...", (_p = statusMsg.completionCode) !== null && _p !== void 0 ? _p : statusMsg.state, " ", (_q = statusMsg.message) !== null && _q !== void 0 ? _q : "").trimEnd();
                                    }
                                    else {
                                        task.output = statusMsg.opIngTitle.concat("...", (_r = statusMsg.message) !== null && _r !== void 0 ? _r : "").trimEnd();
                                    }
                                }
                            }
                            else {
                                // No payload - ignore as a ping/heartbeat
                                task.output = JSON.stringify(raw);
                            }
                        }));
                        // 2. Fire off the async cluster create
                        // this._ui.userMessage(`(CLI says, Starting cluster create...`);
                        task.output = "Invoking operation...";
                        let result = yield trigger(commChannel.socketId);
                        if (result.success) {
                            // 3. listen for real time status (and wait for final result)
                            // await this.monitorExecution(result.output?.taskMap);
                        }
                        else {
                            let logMsg = "Failed invoking operation ".concat(mainOpCode, " [CID ", (_b = (_a = result.output) === null || _a === void 0 ? void 0 : _a.correlationId) !== null && _b !== void 0 ? _b : "none", "]: ", (_g = (_e = (_c = result.message) !== null && _c !== void 0 ? _c : (_d = result.error) === null || _d === void 0 ? void 0 : _d.message) !== null && _e !== void 0 ? _e : (_f = result.error) === null || _f === void 0 ? void 0 : _f.stack) !== null && _g !== void 0 ? _g : "no details available");
                            this.logger.error(logMsg, result.error);
                            let friendlyMsg = "Failed invoking operation: ".concat((_k = (_h = result.message) !== null && _h !== void 0 ? _h : (_j = result.error) === null || _j === void 0 ? void 0 : _j.message) !== null && _k !== void 0 ? _k : "See logs for details");
                            // Close up shop and throw
                            // task.output = friendlyMsg;
                            task.task.complete();
                            result.message = friendlyMsg;
                            ctx.res = result;
                            this.removeStatusListeners();
                            reject(result); // <-- result is getting treated like an Error.  Ok, cuz we want to send out the friendly message
                        }
                    }));
                })
            }, {
                renderer: 'default',
                rendererOptions: { timer: listr2_1.PRESET_TIMER }
            });
            let taskResult = yield (spinners === null || spinners === void 0 ? void 0 : spinners.run()); // we're not going to await because we cant block execution (we havent fired the actual task yet)
            // this._ui.userMessage("CLI says, spinner task ended. ".concat(JSON.stringify(taskResult)));
            yield this.msgClient.disconnect();
            // return <TResult>{ success: true, message: "Process execution completed" };  // TODO: Capture the result from the completion status message
            return taskResult.res;
        });
    }
};
LrpWatcher = tslib_1.__decorate([
    (0, inversify_1.injectable)(),
    tslib_1.__param(1, (0, inversify_1.inject)(codiac_common_1.INTERFACES.IBetterLogger)),
    tslib_1.__metadata("design:paramtypes", [Object, Object])
], LrpWatcher);
exports.LrpWatcher = LrpWatcher;
//# sourceMappingURL=lrp-watcher.js.map