"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const _ = require("lodash");
const command_base_exec_tenant_1 = require("../../../command-base-exec-tenant");
const cli_common_1 = require("../../../cli-common");
class ClusterAgentInstall extends command_base_exec_tenant_1.CommandBaseExecTenant {
    constructor() {
        // static hidden = true;
        super(...arguments);
        this.adminOnly = true;
    }
    captureArgs() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { args, flags } = yield this.parse(ClusterAgentInstall);
            let partial = {};
            if (args.cluster)
                partial.cluster = args.cluster;
            if (flags.version)
                partial.version = flags.version;
            // ---------------------------------------------------------------
            // ---------------------------------------------------------------
            const takeDefaults = flags['take-defaults'];
            return [partial, takeDefaults];
        });
    }
    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.");
            const found = rootMap.clusters.find(c => c.name == partial.cluster);
            if (found == undefined)
                throw new Error(`No cluster found with name [${partial.cluster}].`);
            return Object.assign({ cluster: partial.cluster }, (partial.version ? { version: partial.version } : {}));
        });
    }
    buildCandidate_interactively(partial, takeDefaults, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let clusters = rootMap.clusters.map(c => c);
            if (partial.cluster) {
                const found = clusters.find(c => c.name == partial.cluster);
                if (found == undefined) {
                    this._ui.userMessage(this._styler.colorWarning(`No cluster found with name [${partial.cluster}]; please select from the list below.`));
                    partial.cluster = undefined;
                }
            }
            let selected;
            if (clusters.length == 1 && takeDefaults) {
                selected = clusters[0];
            }
            else {
                selected = yield this.rootMapUtils.promptForCluster(clusters, partial.cluster);
            }
            partial.cluster = selected.name;
            partial.version = yield this.promptForVersion(partial.version);
            return yield this.buildCandidate_silently(partial, rootMap);
        });
    }
    promptForVersion(userInput) {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (userInput != undefined) {
                this._ui.userMessage(`Installing version: ${this._styler.hilite(userInput)}`);
                return userInput;
            }
            const versions = yield this.fetchEnvoyVersions();
            const latestLabel = `(latest)  ${(_b = (_a = versions[0]) === null || _a === void 0 ? void 0 : _a.version) !== null && _b !== void 0 ? _b : ''}`.trim();
            const choices = [
                { name: latestLabel, value: '' },
                ...versions.map(v => ({
                    name: v.publishedAt
                        ? `${v.version}  ${this._styler.dim(new Date(v.publishedAt).toLocaleDateString())}`
                        : v.version,
                    value: v.version,
                })),
            ];
            const fetchChoices = (search) => tslib_1.__awaiter(this, void 0, void 0, function* () { return choices.filter(c => !search || c.name.includes(search)); });
            const fuzzySelector = new cli_common_1.PromptSelectFuzzy(this.logger, this._ui, this._styler);
            const selected = yield fuzzySelector.go('chartVersion', 'Select version to install:', false, undefined, false, fetchChoices);
            return selected || undefined;
        });
    }
    fetchEnvoyVersions() {
        var _a, _b, _c, _d;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                this._ui.startSpinner('Fetching available versions...');
                const result = yield this.genRelayClient.Call.clusterEnvoyVersionsFetch();
                this._ui.stopSpinner(`${(_b = (_a = result.output) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0} versions found`);
                return (_c = result.output) !== null && _c !== void 0 ? _c : [];
            }
            catch (err) {
                this._ui.stopSpinner('could not fetch versions');
                this.logger.warn(`Failed to fetch codiac envoy versions: ${(_d = err === null || err === void 0 ? void 0 : err.message) !== null && _d !== void 0 ? _d : err}`);
                return [];
            }
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("--silent");
        cmd.push(candidate.cluster);
        if (candidate.version)
            cmd.push("--version", candidate.version);
        return cmd;
    }
    executeTask(candidate) {
        var _a, _b, _c;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                const result = yield this.watcher.triggerAndWatch((correlationId, socketId) => this.genRelayClient.Call.clusterEnvoyInstall({
                    spec: Object.assign({ clusterName: candidate.cluster }, (candidate.version ? { version: candidate.version } : {})),
                    socketId: socketId,
                    correlationId: correlationId,
                }));
                if (result.error) {
                    const msg = `Error installing Codiac agent on cluster [${candidate.cluster}]: ${(_a = result.message) !== null && _a !== void 0 ? _a : ""} ${(_b = result.error.message) !== null && _b !== void 0 ? _b : ""}`.trimEnd();
                    this.logger.error(msg, result.error);
                    this._ui.userMessage(`${this._styler.colorCritical("ERROR!")} ${msg}`);
                }
                else if (!result.success) {
                    const msg = `Codiac agent install failed on cluster [${candidate.cluster}]: ${(_c = result.message) !== null && _c !== void 0 ? _c : ""}`.trimEnd();
                    this.logger.notice(msg, result);
                    this._ui.userMessage(`${this._styler.colorCritical("FAILED!")} ${msg}`);
                }
                else {
                    const msg = `${this._styler.colorGood("SUCCESS!")} Codiac agent installed on cluster [${this._styler.hilite(candidate.cluster)}].`;
                    this.logger.notice(msg, result);
                    this._ui.userMessage(msg);
                }
            }
            catch (err) {
                throw err;
            }
            finally {
                return;
            }
        });
    }
}
exports.default = ClusterAgentInstall;
ClusterAgentInstall.description = 'Installs the Codiac agent on the given cluster, enabling Codiac to manage workloads and configurations on the cluster.';
ClusterAgentInstall.aliases = ['cluster:envoy:install'];
ClusterAgentInstall.examples = [
    {
        description: 'Install the Codiac agent on a cluster.',
        command: '<%= config.bin %> <%= command.id %> my-cluster',
    },
    {
        description: 'Install a specific version of the Codiac agent.',
        command: '<%= config.bin %> <%= command.id %> my-cluster --version 1.2.3',
    },
    {
        description: 'Non-interactive (scripted) invocation.',
        command: '<%= config.bin %> <%= command.id %> my-cluster --silent',
    },
    {
        description: 'Renders the equivalent silent command and then executes.',
        command: '<%= config.bin %> <%= command.id %> my-cluster --echo',
    },
    {
        description: 'Render the equivalent silent command without executing.',
        command: '<%= config.bin %> <%= command.id %> my-cluster --to-script',
    },
];
ClusterAgentInstall.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: "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 where the command needs to override invalid user input; such cases will always prompt for confirmation." }),
    version: core_1.Flags.string({ char: 'v', description: 'Version of the Codiac agent helm chart to install.  Omit to install the latest available version.' }),
};
ClusterAgentInstall.args = {
    cluster: core_1.Args.string({ description: 'Name of the cluster in Codiac on which to install the Codiac agent.  You can use `cod cluster list` to see available cluster names.' }),
};
//# sourceMappingURL=install.js.map