"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const _ = require("lodash");
const prettify_1 = require("../../../prettify");
const contracts_1 = require("../../../apis/codiac-relay/contracts");
const command_base_exec_tenant_1 = require("../../../command-base-exec-tenant");
const config_ui_utils_1 = require("../../../uilogic/config-ui-utils");
class NocClusterCapture extends command_base_exec_tenant_1.CommandBaseExecTenant {
    captureArgs() {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { args, flags } = yield this.parse(NocClusterCapture);
            // 1. Set initial property values from cmd args
            let partial = {
                name: flags.name,
                provider: flags.provider,
                providerSubscription: flags.providerSubscription,
                providerTenantId: flags.providerTenantId,
                locationName: flags.location,
                providerGroup: flags.azResourceGroup
            };
            // ---------------------------------------------------------------
            // 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];
        });
    }
    buildCandidate_silently(partial, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (partial.name == undefined || _.isEmpty(partial.name))
                throw new Error("Missing cluster name.");
            if (partial.provider == undefined || _.isEmpty(partial.provider))
                throw new Error("Missing cloud service provider.");
            if (partial.providerSubscription == undefined || _.isEmpty(partial.providerSubscription))
                throw new Error("Missing cloud service provider subscription Id.");
            if (partial.locationName == undefined || _.isEmpty(partial.locationName))
                throw new Error("Missing cluster location.");
            if (contracts_1.CloudProviderEnum[partial.provider] == undefined)
                throw new Error("Invalid cloud service provider.");
            if (contracts_1.CloudProviderEnum[partial.provider] == contracts_1.CloudProviderEnum.azure && partial.providerGroup == undefined)
                throw new Error("Missing Azure resource group.");
            let candidate = {
                name: partial.name,
                provider: partial.provider,
                providerSubscription: partial.providerSubscription,
                locationName: partial.locationName,
                providerGroup: partial.providerGroup
            };
            return candidate;
        });
    }
    buildCandidate_interactively(partial, takeDefaults, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let defaults; // This is a leftover legacy pattern.  TODO: refactor into partial/candidate pattern.
            let confirmed = false;
            do {
                console.clear();
                this._ui.userMessage(this._styler.bold("Capture Cluster:"));
                // TODO: ask to change before prompting the list
                let allPvds = this.cspUiFactory.getAllClusterProviders(this.ioc);
                partial.provider = yield this.cspContextualizer.promptForCloudProvider(allPvds, partial.provider);
                const cspAcct = yield this.cspContextualizer.ensureCspTenantContext(this._codiacApi, partial.provider, partial.providerSubscription, partial.providerTenantId, false);
                partial.providerTenantId = cspAcct.tenantId;
                let cspUser = yield this.cspContextualizer.promptForCloudProviderCreds(this.ioc, partial.provider, undefined, undefined, undefined, cspAcct);
                // Adhere to the subscription of the current csp user (if any specified).
                if (partial.providerSubscription == undefined && cspUser.subscriptionId) {
                    partial.providerSubscription = cspUser.subscriptionId;
                }
                // load up the cluster configurator for the given clouduprovider
                let regCfg = this.cspUiFactory.create(partial.provider, this.ioc);
                let def = yield regCfg.defineClusterCaptureParams(partial, rootMap, defaults, partial.providerTenantId, cspUser); // note: "defaults" gets mutated here
                defaults = def.defaults;
                partial = def.spec;
                // console.clear();
                let msg = (0, prettify_1.prettify)(partial);
                this._ui.userMessage(msg);
                this._ui.userMessage(`You are about to capture this cluster. Continue?`);
                confirmed = yield this._ui.promptConfirm("confirmCreate", `(hit 'N' to edit your input)`, false);
            } while (!confirmed);
            let candidate = {
                name: partial.name,
                provider: partial.provider,
                providerSubscription: partial.providerSubscription,
                locationName: partial.locationName,
                providerGroup: partial.providerGroup,
                ingressDef: partial.ingressDef
            };
            return candidate;
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("--silent");
        cmd.push("-n", candidate.name);
        cmd.push("-p", candidate.provider);
        cmd.push("-s", candidate.providerSubscription);
        cmd.push("-l", candidate.locationName);
        if (candidate.provider == contracts_1.CloudProviderEnum.azure) {
            cmd.push("-g", candidate.providerGroup);
        }
        return cmd;
    }
    executeTask(candidate) {
        var _a, _b, _c;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            // ----------------------------------------------------
            // THIS IS NOT the design we're looking for.  
            // TODO: Use the request as the candidate and just fire it here.
            let req = {
                provider: candidate.provider,
                providerSubscriptionId: candidate.providerSubscription,
                name: candidate.name,
            };
            if (candidate.ingressDef != undefined) {
                req.ingressDef = {
                    internal: candidate.ingressDef.internal,
                    disableExternal: candidate.ingressDef.disableExternal
                };
            }
            if (candidate.provider == contracts_1.CloudProviderEnum.aws)
                req.awsRegion = candidate.locationName;
            if (candidate.provider == contracts_1.CloudProviderEnum.azure) {
                req.azureResourceGroup = candidate.providerGroup;
                if ((_a = candidate.ingressDef) === null || _a === void 0 ? void 0 : _a.ip_name) {
                    req.ingressDef = Object.assign(Object.assign({}, req.ingressDef), { ip_name: candidate.ingressDef.ip_name });
                }
            }
            // ----------------------------------------------------
            let result = yield this.genRelayClient.Call.clusterCapture(req);
            if (result.error != undefined) {
                throw result.error;
            }
            else if (result.success == true) {
                this._ui.userMessage((_b = result.message) !== null && _b !== void 0 ? _b : "Successfully captured ".concat("[", candidate.provider, "] cluster ", "[", candidate.name, "]"));
            }
            else {
                this._ui.userMessage((_c = result.message) !== null && _c !== void 0 ? _c : "Cluster ".concat("[", candidate.name, "] was not found in the given [", candidate.provider, "] subscription."));
            }
        });
    }
}
exports.default = NocClusterCapture;
NocClusterCapture.description = "Creates a new record in Codiac for a cluster that already physically exists in a cloud subscription.  \
    You will need credentials for the cloud service provider subscription you are drawing the cluster from.  \
    Use `cod csp login` to capture your credentials.  \
    Use `cod cluster forget ---running` to undo this operation.";
NocClusterCapture.dependsOn = ["name", "provider", "providerSubscription", "location"];
NocClusterCapture.aliases = ["cluster:capture"];
NocClusterCapture.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    name: core_1.Flags.string({ char: 'n', description: 'Name of the cluster to capture' }),
    provider: core_1.Flags.string({ char: 'p', required: false, options: [contracts_1.CloudProviderEnum.azure, contracts_1.CloudProviderEnum.aws], description: 'Cloud service provider on which to find the cluster' }),
    providerSubscription: core_1.Flags.string({ char: 's', required: false, description: 'The cloud provider subscription Id under which to find the cluster (eg: SubscriptionId for azure, AccountId for aws).' }),
    providerTenantId: core_1.Flags.string({ char: 't', description: '(in silent mode, either this or providerSubscription is required if you have more than one tenant profile on a given cloud provider) The Id of the cloud provider tenant under which to authenticate.' }),
    location: core_1.Flags.string({ char: 'l', required: false, description: 'The short name of the regional data center in which the cliuster resides.' }),
    azResourceGroup: core_1.Flags.string({ char: 'g', required: false, description: '(required for Azure) The Azure resource group in which to find the cluster.' }),
    // TODO: Move these into the base class
    silent: core_1.Flags.boolean({ exclusive: ["echo", "to-script"], dependsOn: ["name", "provider", "providerSubscription", "location"], 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": 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." })
};
NocClusterCapture.args = {};
NocClusterCapture.examples = [
    { description: "Capture a cluster interatively.", command: "cod cluster capture" },
    { description: "Capture an Azure cluster silently.", command: "cod cluster capture -n my-cluster -p azure -s abcd123-xyzpdq-5678-pdq345 -l eastus -g our-dev-stuff" },
    { description: "Capture an AWS cluster silently.", command: "cod cluster capture -n my-cluster -p aws -s 123456789012 -l us-east-1" },
    // { description: "Capture a cluster from params in a data file.", command: "cat myparams.json | cod cluster capture" },
];
//# sourceMappingURL=capture.js.map