"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LocalCommandRunner = void 0;
const tslib_1 = require("tslib");
const _ = require("lodash");
const path = require("path");
const inversify_1 = require("inversify");
const codiac_common_1 = require("@codiac.io/codiac-common");
const contracts_1 = require("@codiac.io/codiac-common/contracts");
const terminal_utils_1 = require("../terminal-utils");
const entities_1 = require("../entities");
const INTERFACES_CLI_1 = require("../INTERFACES_CLI");
let LocalCommandRunner = class LocalCommandRunner {
    constructor(msgClient, cliEnviro, termUtils, logger) {
        this.msgClient = msgClient;
        this.cliEnviro = cliEnviro;
        this.termUtils = termUtils;
        this.logger = logger;
        this.subject = "mylocalmachine.executeinterminal";
    }
    /** IMPORTANT! This method requires the client to be connected first. */
    listen() {
        var _a;
        try {
            // let subject = ;
            this.localTerminalCommandRunnerHandlerId = this.msgClient.subscribe(this.subject, (err, msg, meta, raw) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                try {
                    yield this.cliCommandHandler(err, msg, meta, raw);
                    return;
                }
                catch (err) {
                    throw err;
                }
            }));
            return;
        }
        catch (err) {
            err.message = "Error setting up command handler: ".concat((_a = err.message) !== null && _a !== void 0 ? _a : "(check logs for details)");
            throw err;
        }
    }
    cliCommandHandler(err, msg, meta, raw) {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            // 1) Execute the command in a terminal
            this.logger.debug("Terminal command received", msg);
            let response = new contracts_1.SingleResult(false, undefined, undefined, { code: 1, stdout: "Nothing to see here; move along." });
            try {
                const replacements = Object.assign({}, _.clone(this.cliEnviro));
                replacements.cliConfigDir = path.normalize(replacements.cliConfigDir);
                let ultReq = _.cloneDeep(msg);
                ultReq.env = Object.assign(Object.assign({}, process.env), msg.env);
                ultReq.command = this.performTokenReplacements("cli command", ultReq.command, replacements);
                response.output = yield this.termUtils.execute(ultReq);
            }
            catch (err) {
                response.output.code = 1; // generic error code (if we're here, then we're not able to parse it from the terminal output)
                response.output.error = err;
                response.message = (_a = err.message) !== null && _a !== void 0 ? _a : response.message;
            }
            finally {
                response.success = Boolean(response.output.code == 0);
                if (response.output) {
                    if (response.output.error && !_.isEmpty(response.output.error)) {
                        response.error = response.output.error;
                        if (response.error.message && !_.isEmpty(response.error.message))
                            response.message = response.output.error.message;
                    }
                }
            }
            // 2) Reply with results
            try {
                let responseMeta = {
                    action: meta.action,
                    correlationId: meta.correlationId,
                    subject: (_b = meta.replyOn) !== null && _b !== void 0 ? _b : this.subject
                };
                yield this.msgClient.publish(response, responseMeta);
                return;
            }
            catch (err) {
                throw err;
            }
        });
    }
    /** Performs token replacement on the given string using loDash's html view engine.
     * This method DOES NOT mutate the given string; it only returns the new value.
     *
     * **Token delimiters**:
     * * interpolate:  `<%= user %>`  or `${user}`
     * * html-escape:  `<%- value %>`
     * * backslashes to treat delimiters as plain text: `<%= "\\<%- value %\\>" %>`
     *
     * For more examples, see: [LoDash template command](https://lodash.com/docs/4.17.15#template)
     * &nbsp;
     *
     * **EXAMPLE**: Use the "interpolate" delimiter to create a compiled template.
     * ```typescript
     * let output = performTokenReplacements('identifier for this string', 'hello <%= user %>!', { 'user': 'fred' });
     * ```
     * ...yields...
     * ```typescript
     * 'hello fred!'
     * ```
  
     * Errors are logged and ignored.
     *
     */
    performTokenReplacements(templateName, template, variables) {
        var _a;
        try {
            // Catches the variable placeholders inside a string, eg:  "https://${asset-code}.${cabinet}.${tenant}.oncodiac.io"
            // let ptn = /\$\{([\w\d\._]+)\}/g;
            // let re = new RegExp(ptn);
            // let matches = re.exec(setting.value);  // would be faster to make this a distinct list of variable names, since we're doing a global replace on the callouts.
            // let newValue = setting.value;
            // for (let match in matches) {
            //   let variableName = match[0];  // the capture without the callout delimiters 
            //   if (variables.contains(variablesName)) {
            //     let callout = "${" + variableName + "}";  // NOTE: validate that these delims are indeed the ones we are supporting 
            //     let actual = variables[variableName];
            //     newValue = newValue.replace(callout, actual);  
            //     this.logger.trace(`Replaced config variable callout: [${variableName}] in setting: [${setting.setting}], targetFile: [${setting.targetFile}]`);
            //   }
            // }
            let viewEngine = _.template(template);
            let newValue = viewEngine(variables);
            return newValue;
        }
        catch (err) {
            this.logger.detail(`Error performing token replacements on ${templateName}: ${(_a = err.message) !== null && _a !== void 0 ? _a : err.stack}`);
            return template;
        }
    }
};
LocalCommandRunner = tslib_1.__decorate([
    (0, inversify_1.injectable)(),
    tslib_1.__param(0, (0, inversify_1.inject)(INTERFACES_CLI_1.INTERFACES_CLI.IMessagingClient)),
    tslib_1.__param(1, (0, inversify_1.inject)(entities_1.CliEnviro)),
    tslib_1.__param(2, (0, inversify_1.inject)(terminal_utils_1.TerminalUtils)),
    tslib_1.__param(3, (0, inversify_1.inject)(codiac_common_1.INTERFACES.IBetterLogger)),
    tslib_1.__metadata("design:paramtypes", [Object, entities_1.CliEnviro,
        terminal_utils_1.TerminalUtils, Object])
], LocalCommandRunner);
exports.LocalCommandRunner = LocalCommandRunner;
//# sourceMappingURL=local-command-runner.js.map