"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const _ = require("lodash");
const config_ui_utils_1 = require("../../uilogic/config-ui-utils");
const command_base_exec_tenant_1 = require("../../command-base-exec-tenant");
const type_safety_utils_1 = require("../../uilogic/type-safety-utils");
const local_command_runner_1 = require("../../ops/terminal-command-runner/local-command-runner");
const terminal_utils_1 = require("../../ops/terminal-utils");
const clusterProjxn = { pathsIncluded: ["id", "name", "provider", "locationName", "instance", "modified", "modifiedBy"], pathsExcluded: [] };
class ClusterStop extends command_base_exec_tenant_1.CommandBaseExecTenant {
    constructor() {
        super(...arguments);
        this.adminOnly = true;
    }
    // --------------------------------------------------------------------
    // Lazy-loaded properties
    // protected get k8sUtils(): K8sUtils {
    //   if (this._k8sUtils_backer === undefined) {
    //     this._k8sUtils_backer = this.ioc.get(K8sUtils);
    //   }
    //   return this._k8sUtils_backer;
    // }
    // private _k8sUtils_backer: K8sUtils | undefined;
    get termUtils() {
        if (this._termUtils_backer === undefined) {
            this._termUtils_backer = this.ioc.get(terminal_utils_1.TerminalUtils); // new TerminalUtils(this.logger);
        }
        return this._termUtils_backer;
    }
    get localCommandRunner() {
        if (this._localCommandRunner_backer === undefined) {
            this._localCommandRunner_backer = this.ioc.get(local_command_runner_1.LocalCommandRunner); // new LocalCommandRunner(this.msgClient, this.cliEnviro, this.termUtils, this.logger); 
        }
        return this._localCommandRunner_backer;
    }
    // --------------------------------------------------------------------
    bootstrap() {
        super.bootstrap();
        this.ioc.bind(terminal_utils_1.TerminalUtils).toDynamicValue(ctx => new terminal_utils_1.TerminalUtils(this.logger));
        this.ioc.bind(local_command_runner_1.LocalCommandRunner).toDynamicValue(ctx => new local_command_runner_1.LocalCommandRunner(this.msgClient, this.cliEnviro, this.termUtils, this.logger));
    }
    captureArgs() {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { args, flags } = yield this.parse(ClusterStop);
            let partial = {};
            if (args.cluster)
                partial.cluster = args.cluster;
            // ---------------------------------------------------------------
            // TODO: move everything from here down into the base class
            // ---------------------------------------------------------------
            const interactionMode = (this.pipedInput) ? config_ui_utils_1.InteractionModes.silent : (_b = (_a = undefined !== null && undefined !== void 0 ? undefined : (flags.echo ? config_ui_utils_1.InteractionModes.echo : undefined)) !== null && _a !== void 0 ? _a : (flags["to-script"] ? config_ui_utils_1.InteractionModes.toscript : undefined)) !== null && _b !== void 0 ? _b : (flags.silent ? config_ui_utils_1.InteractionModes.silent : undefined);
            const takeDefaults = flags['take-defaults'];
            return [partial, interactionMode, takeDefaults];
        });
    }
    // /** Throws on invalid */
    // private validate(partial: Partial<IAuthRoleDef>): void {
    //   if (partial.name == undefined || _.isEmpty(partial.name)) throw new Error("Missing name");
    //   let rxName = /^[a-zA-Z][a-zA-Z0-9-]{2,50}$/;
    //   if (!rxName.test(partial.name)) throw new Error("Invalid name: must be 3- to 50-character string of alphanumerics and hyphens, starting with a letter.");
    // }
    buildCandidate_silently(partial, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (partial.cluster == undefined || _.isEmpty(partial.cluster))
                throw new Error("Must specify cluster.");
            // Enforce a valid local cluster
            const found = rootMap.clusters.find(c => c.name == partial.cluster);
            if (found == undefined) {
                throw new Error("No cluster found with that name.");
            }
            else if (type_safety_utils_1.TypeSafetyUtils.toBoolean(found === null || found === void 0 ? void 0 : found.thisMachine) != true) {
                throw new Error("This command is only applicable to clusters that exist on this machine.");
            }
            let candidate = {
                cluster: partial.cluster
            };
            return candidate;
        });
    }
    buildCandidate_interactively(partial, takeDefaults, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            // Enforce a valid local cluster
            let forceConfirm = false;
            if (partial.cluster) {
                const found = rootMap.clusters.find(c => c.name == partial.cluster);
                if (found == undefined) {
                    partial.cluster = undefined;
                    forceConfirm = true;
                }
                else if (type_safety_utils_1.TypeSafetyUtils.toBoolean(found === null || found === void 0 ? void 0 : found.thisMachine) != true) {
                    partial.cluster = undefined;
                    forceConfirm = true;
                }
            }
            let clusters = rootMap.clusters.filter(c => type_safety_utils_1.TypeSafetyUtils.toBoolean(c.thisMachine) == true)
                .map(c => c);
            let selected;
            if (clusters.length == 1 && (takeDefaults == true)) {
                selected = clusters[0];
            }
            else {
                selected = yield this.promptForCluster(clusters, partial.cluster);
            }
            partial.cluster = selected.name;
            // Prompt for output format
            return yield this.buildCandidate_silently(partial, rootMap);
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("--silent");
        cmd.push(candidate.cluster);
        return cmd;
    }
    executeTask(candidate) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let socketId = yield this.msgClient.connect();
                this.localCommandRunner.listen(); // to fire off any local machine terminal commands requested by the relay during the command
                let result = yield this.watcher.triggerAndWatch((socketId) => this.genRelayClient.Call.stopCluster({ cluster: candidate.cluster, socketId: socketId }));
                if (result.error) {
                    this.logger.error(`Error stopping cluster: ${result.message || ""}; ${result.error.message}`, result.error);
                    this._ui.userMessage(`Error stopping cluster: ${result.message || ""}; ${result.error.message}`);
                }
                else if (!result.success) {
                    this.logger.notice(`Cluster stop failed without error. ${result.message}`);
                    this._ui.userMessage(`Cluster stop failed without error. ${result.message}`);
                }
                else {
                    const msg = this._styler.colorGood("SUCCESS!").concat(" Stopped cluster [", this._styler.hilite(candidate.cluster), "].");
                    this.logger.notice(msg, result);
                    this._ui.userMessage(msg);
                }
            }
            catch (err) {
                throw err;
            }
            finally {
                // if (this.msgClient.isConnected()) {
                //   await this.msgClient.disconnect();
                // }
                return;
            }
        });
    }
    /** Renders a user-friendly cluster description. */
    describe(cluster) {
        return cluster.name.concat(" ", this._styler.dim("(" + cluster.provider + ")"));
    }
    /** Returns the name of the selected cluster.
    */
    promptForCluster(clusters, defaultValue) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let output;
            let keep = false;
            if (defaultValue && clusters.find(c => c.name === defaultValue)) {
                keep = yield this._ui.promptConfirm("clusterNameConfirm", `Local Cluster: [${this._styler.hilite(defaultValue)}]`, true);
            }
            if (keep === true) {
                output = clusters.find(c => c.name === defaultValue);
            }
            else {
                let choices = clusters
                    .map(c => { return { name: this.describe(c), value: c.name }; });
                let selectedName = (yield this._ui.promptSelect("clusterName", "Select the local cluster:", choices));
                output = clusters.find(c => c.name === selectedName);
            }
            return output;
        });
    }
}
exports.default = ClusterStop;
ClusterStop.description = 'For local machine clusters only.  (Idempotent) Ensures that the specified local machine cluster is running and not inactive.  Clusters can consume significant local resources, since they cannot be scaled like they can in the cloud, so this command and `cluster stop` together enable a user to determine which a clusters are actually running or not at any given time.';
ClusterStop.aliases = [];
ClusterStop.examples = [
    '<%= config.bin %> cluster start my-fav-cluster'
];
ClusterStop.flags = {
    // TODO: Move these into the base class
    silent: core_1.Flags.boolean({ exclusive: ["echo", "to-script"], description: 'Non-Interactive mode; executes without any user interaction and fails on any missing or invalid arguments.' }),
    echo: core_1.Flags.boolean({ exclusive: ["to-script", "silent"], description: 'Echo interaction mode; renders the equivalent non-interactive cli command for future use before final execution.' }),
    "to-script": core_1.Flags.boolean({ exclusive: ["echo", "silent"], description: 'Toscript interaction mode; renders the equivalent non-interactive cli command WITHOUT any execution.' }),
    "take-defaults": core_1.Flags.boolean({ exclusive: ["silent"], description: "Setting this to true prevents prompting for confirmation on parameters that were passed in or were automatically set to default values (Irrelevant in --silent mode).  This behavior does NOT apply to scenarios that the command needs to override invalid user input; such cases will always prompt for confirmation.  eg: when no argument was provided for file or type, and only one exists, the system will render the autoselected file unless this flag is set." })
};
ClusterStop.args = {
    cluster: core_1.Args.string({ description: 'Name of the LOCAL cluster in Codiac (Optional: required only if you have more than one cluster for the current organization on this machine).  You can use `cod cluster list` to see the names of your codiac clusters.' }),
};
//# sourceMappingURL=stop.js.map