"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 k8s_utils_1 = require("../../ops/k8s/k8s-utils");
const clusterProjxn = { pathsIncluded: ["id", "name", "provider", "locationName", "instance", "modified", "modifiedBy"], pathsExcluded: [] };
class ClusterConnect extends command_base_exec_tenant_1.CommandBaseExecTenant {
    constructor() {
        super(...arguments);
        this.adminOnly = true;
    }
    // --------------------------------------------------------------------
    // Lazy-loaded properties
    get k8sUtils() {
        if (this._k8sUtils_backer === undefined) {
            this._k8sUtils_backer = this.ioc.get(k8s_utils_1.K8sUtils);
        }
        return this._k8sUtils_backer;
    }
    // --------------------------------------------------------------------
    bootstrap() {
        super.bootstrap();
        k8s_utils_1.K8sUtils.bootstrap(this.ioc, this);
    }
    captureArgs() {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { args, flags } = yield this.parse(ClusterConnect);
            let partial = {};
            if (args.cluster)
                partial.cluster = args.cluster;
            /*if (flags['force-refresh']) */ partial.forceRefresh = true; // ALWAYS refresh.
            // ---------------------------------------------------------------
            // 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) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (partial.cluster == undefined || _.isEmpty(partial.cluster))
                throw new Error("Must specify cluster.");
            let candidate = {
                cluster: partial.cluster,
                forceRefresh: partial.forceRefresh
            };
            return candidate;
        });
    }
    buildCandidate_interactively(partial, takeDefaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let clusters = yield this.loadClusters();
            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);
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("--silent");
        cmd.push(candidate.cluster);
        if (candidate.forceRefresh)
            cmd.push("--force-refresh");
        return cmd;
    }
    executeTask(candidate) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let k8sConfig = yield this.k8sUtils.fetchKubeConfigForCluster(candidate.cluster, candidate.forceRefresh);
            yield this.k8sUtils.cacheWrite(k8sConfig.currentContext, k8sConfig);
            this._ui.userMessage(this._styler.colorGood("Success!").concat(" Captured creds and set default cluster context for ", this._styler.hilite(candidate.cluster)));
            // ============end.
            // let machineConfig = new KubeConfig();
            // machineConfig.loadFromDefault();
            // machineConfig.mergeConfig(k8sConfig, false);
            // machineConfig.setCurrentContext(k8sConfig.currentContext);
            // let targetFile = process.env["KUBECONFIG"];
            // if (!targetFile) {
            //   let homeDir = "~/"; // path.posix.resolve("~/");  // NOTE:  This tilde (~) may not be valid on a windows box.
            //   let pathName = path.posix.join(OpsUtils.resolveHomeDir(homeDir), CliConstants.LOCAL_KUBE_CONFIG_PATH_NAME);
            //   let json = machineConfig.exportConfig();
            //   if (!fs.existsSync(path.dirname(pathName))) {
            //     await fs.promises.mkdir(path.dirname(pathName), { recursive: true });
            //   }
            //   await fs.promises.writeFile(pathName, json);
            //   this._ui.userMessage("current k8s context set to ".concat(machineConfig.currentContext, "."));
            // }
            return;
        });
    }
    // TODO: Move these fxns to a shared class (along w their copies in `cod cluster journal`)
    loadClusters() {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                // TODO: use rootmap instead...
                let readResult = yield this._codiacApi.ClusterDef.tryReadMany({ all: true }, { projection: clusterProjxn });
                let clusterDefs = (_b = (_a = readResult.output) === null || _a === void 0 ? void 0 : _a.map(c => c)) !== null && _b !== void 0 ? _b : [];
                clusterDefs = _.orderBy(clusterDefs, c => c.name);
                return clusterDefs;
            }
            catch (err) {
                throw err;
            }
        });
    }
    /** Renders a user-friendly cluster description. */
    describe(cluster) {
        return `${cluster.name} ${this._styler.dim("(" + cluster.provider + (cluster.locationName ? ", " + cluster.locationName : "") + ")")}`;
    }
    /** 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", `Target 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 target cluster:", choices));
                output = clusters.find(c => c.name === selectedName);
            }
            return output;
        });
    }
}
exports.default = ClusterConnect;
ClusterConnect.description = 'Downloads the kube config context for the current user on the given cluster, writes it to the local machine kube config file, and sets it as the current default context.  NOTE: Codiac keeps its own cache of the cluster connection credentials; this command is purely to facilitate the use of other software on the local machine that the user may want to point to clusters in Codiac.';
ClusterConnect.aliases = [];
ClusterConnect.examples = [
    '<%= config.bin %> <%= command.id %> my-fav-cluster'
];
ClusterConnect.flags = {
    // "force-refresh": Flags.boolean({ char: 'f', description: 'Prevents a cache hit for the cluster connection and forces a new fetch from the remote cluster itself.' }),
    // 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." })
};
ClusterConnect.args = {
    cluster: core_1.Args.string({ description: 'Name of the cluster in Codiac.  You can use `cod cluster list` to see the names of your codiac clusters.' }),
};
//# sourceMappingURL=connect.js.map