"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AwsResourceConfigurator = void 0;
const tslib_1 = require("tslib");
const inversify_1 = require("inversify");
const _ = require("lodash");
const codiac_common_1 = require("@codiac.io/codiac-common");
const image_registry_1 = require("@codiac.io/codiac-domain/image-registry");
const codiac_ops_common_1 = require("@codiac.io/codiac-ops-common");
const contracts_1 = require("../../apis/codiac-api/contracts");
const codiac_relay_1 = require("../../apis/codiac-relay");
const codiac_constants_1 = require("../../codiac-constants");
const contracts_2 = require("../../relay/contracts");
const ops_1 = require("../../ops");
const ingress_exposure_enum_1 = require("../../codiac-entities/ingress-exposure-enum");
const cli_common_1 = require("../../cli-common");
const type_safety_utils_1 = require("../../uilogic/type-safety-utils");
/** Walks the user through the selection of an existing
 * or the declaration of a new image registry.
 */
let AwsResourceConfigurator = class AwsResourceConfigurator {
    constructor(genRelayClient, codiacUser, _ui, _styler, logger) {
        this.genRelayClient = genRelayClient;
        this.codiacUser = codiacUser;
        this._ui = _ui;
        this._styler = _styler;
        this.logger = logger;
        this.cloudProvider = contracts_1.CloudProviderEnum.aws;
    }
    captureSecretStore(defaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let output;
                // const cspUser = await this.relayClient.getCurrentUserFor(this.cloudProvider);
                const cspUser = (yield this.getAwsUserInfo(defaults === null || defaults === void 0 ? void 0 : defaults.accountId, true));
                let confirm = false;
                while (confirm !== true) {
                    let region = yield this.promptForLocation(defaults === null || defaults === void 0 ? void 0 : defaults.region);
                    let name = `secretStore|${this.cloudProvider}|${cspUser.accountId}|${region}`;
                    let instance = new contracts_2.AwsSecretStore(name, name, cspUser.accountId, region); // AWS makes this redundant here because it doesnt expose the secret store as an independent resource.
                    output = new contracts_2.AwsSecretStoreDef(name, cspUser.accountId, region, instance);
                    confirm = yield this._ui.promptConfirm("secretStore", `Capture secret store: ${this._styler.hilite(name)} ?`, true);
                }
                return output;
            }
            catch (err) {
                throw err;
            }
        });
    }
    /** Concatenates the secret and session token into a single parseable base64 string */
    crunchForTransport(secretAccessKey, sessionToken) {
        const DELIM = "|";
        let parts = [secretAccessKey];
        if (sessionToken != undefined && (sessionToken.trim() != "")) {
            parts.push(sessionToken);
        }
        let output = parts.map(x => Buffer.from(x).toString('base64')).join(DELIM);
        return output;
    }
    promptToLogin(options) {
        var _a, _b, _c, _d;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let providerAccountId = options === null || options === void 0 ? void 0 : options.providerSubscriptionId;
                let suppressConfirmations = options === null || options === void 0 ? void 0 : options.suppressConfirmations;
                let providedUserName = options === null || options === void 0 ? void 0 : options.providedUserName;
                let providedSecret = options === null || options === void 0 ? void 0 : options.providedSecret;
                let proprietaryInput = options === null || options === void 0 ? void 0 : options.proprietaryInput;
                let isAuthed = false;
                let userName = undefined;
                let secret = undefined;
                let sessionToken = undefined;
                let reason;
                if (!suppressConfirmations) {
                    this._ui.userMessage(`Enter your credentials for ${this._styler.hilite(this.cloudProvider)}`);
                    if (providedUserName && providedUserName.trim() != "") {
                        userName = providedUserName;
                        this._ui.userMessage("Access Key Id: ".concat(this._styler.hilite(userName)));
                    }
                    else {
                        userName = yield this._ui.prompt('regUsername', "Access Key Id:", false);
                    }
                    if (userName === undefined || userName === "")
                        userName = "<token>"; // TODO: make username nullable on the authPvd, so this becomes the job of the auth provider
                    if (providedSecret && providedSecret.trim() != "") {
                        secret = providedSecret;
                        this._ui.userMessage("Secret Access Key: ".concat(this._styler.hilite("(provided)")));
                    }
                    else {
                        secret = yield this._ui.promptPassword('regSecret', `Secret Access Key:`);
                    }
                    if ((proprietaryInput === null || proprietaryInput === void 0 ? void 0 : proprietaryInput.sessionToken) && proprietaryInput.sessionToken.trim() != "") {
                        sessionToken = proprietaryInput.sessionToken;
                        this._ui.userMessage("Session Token: ".concat(this._styler.hilite("(provided)")));
                    }
                    else {
                        let tokenYes = yield this._ui.promptConfirm("keepToken", "Add Session Token? ", false);
                        if (tokenYes) {
                            sessionToken = yield this._ui.promptPassword('regSessionToken', `Session Token:`);
                        }
                    }
                }
                else {
                    if (!providedUserName || !providedSecret)
                        throw new Error("Must provide cloud provider username/pwd to login silent mode");
                    userName = providedUserName;
                    secret = providedSecret;
                    if (proprietaryInput === null || proprietaryInput === void 0 ? void 0 : proprietaryInput.sessionToken)
                        sessionToken = proprietaryInput.sessionToken;
                }
                let cspUser = {
                    tenantCode: this.codiacUser.tenantCode,
                    provider: this.cloudProvider,
                    subscriptionId: providerAccountId,
                    username: userName,
                    created: new Date(Date.now())
                };
                try {
                    this._ui.startSpinner(`Authenticating with ${this.cloudProvider}...`);
                    let req = this.assembleLoginRequest(userName, secret, providerAccountId, sessionToken ? { sessionToken: sessionToken } : undefined);
                    let authResult = yield this.genRelayClient.Call.csp_login(req);
                    if (authResult.error != undefined)
                        throw authResult.error;
                    if (authResult.success != true)
                        throw new Error((_a = authResult.message) !== null && _a !== void 0 ? _a : "no details available");
                    isAuthed = Boolean(authResult.success == true);
                    if (isAuthed == true && authResult.output) {
                        cspUser = authResult.output.cspUser; // overwrite with actual
                    }
                    this._ui.stopSpinner("Success!");
                }
                catch (err) {
                    this.logger.debug(`Error authenticating with ${this.cloudProvider}: ${(_b = err.name) !== null && _b !== void 0 ? _b : ""} ${(_c = err.message) !== null && _c !== void 0 ? _c : ""}`);
                    reason = err.message;
                    this._ui.stopSpinner("Failed.");
                }
                if (isAuthed)
                    this._ui.userMessage(`Logged into ${this._styler.hilite(this.cloudProvider)} as [${this._styler.hilite((_d = cspUser.username) !== null && _d !== void 0 ? _d : "token")}]`);
                else if (reason)
                    this._ui.userMessage(reason);
                return [isAuthed, cspUser];
            }
            catch (err) {
                throw err;
            }
        });
    }
    promptToLogout() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            throw new Error("Interactive logout is not implemented for Aws.");
        });
    }
    assembleLoginRequest(userName, secret, providerAccountId, proprietaryInput) {
        return {
            providerCode: this.cloudProvider,
            providerSubscription: providerAccountId,
            username: userName,
            secret: this.crunchForTransport(secret, proprietaryInput === null || proprietaryInput === void 0 ? void 0 : proprietaryInput.sessionToken)
        };
    }
    // Commented out bc: Replaced with `getAwsUserInfo()` 
    // // TODO: csp user already defines the AWS accountId - look it up instead.
    // // Really though... we cant carry on with one user per csp anymore.  
    // // We may need to switch users midstroke if a resource is on a different csp account.
    // public async promptForAccountId(defaultValue?: string): Promise<string> {
    //   let accountId = (await this._ui.prompt<string>("accountId", "AWS Account Id (ten-digit code):", true, defaultValue))!;
    //   return accountId;
    // }
    /** Returns undefined for invalid creds. */
    getAwsUserInfo(accountId, throwNotFound = false) {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let result = yield this.genRelayClient.Call.getAwsUser({ accountId: accountId }); // <-- TODO: add support for accountId parameter AND return multiples if > 1 applies.  
            if (result.error) {
                throw new Error(`Error retrieving ${this.cloudProvider} account: ${(_a = result.message) !== null && _a !== void 0 ? _a : ""} ${result.error.message}.`);
            }
            else if (throwNotFound == true && result.output == undefined) {
                throw new Error(`No ${this.cloudProvider} account has been authenticated.`);
            }
            return result.output;
        });
    }
    captureImageRegistry(accountId) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                var _a, _b;
                try {
                    // let awsUser = await this.relayClient.getCurrentUserFor(this.cloudProvider);
                    /* TODO: use this instead */
                    // let awsUser = await this.genRelayClient.Call.get_current_user_for({ providerCode: this.cloudProvider });
                    let awsUser = (yield this.getAwsUserInfo(accountId, true));
                    // Get region, default to the one these tokens are for calling out
                    // let region = await this._ui.prompt('scope', 'enter the region of the ECR: ', true, registry.scope || defaults.scope);
                    let isPrivate = yield this._ui.promptConfirm("regAwsIsPrivate", "Private container registry? (hit 'n' for public) ", true);
                    // TODO:  Capture the registry url
                    let registry;
                    if (isPrivate) {
                        // PRIVATE REGION-BASED CONTAINER REGISTRY
                        // url: `${AWS_ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com`
                        // eg:  `570376874173.dkr.ecr.us-east-1.amazonaws.com`
                        // regUrl = (await this._ui.prompt("regUrl", "Enter the private registry base url"))!;
                        // let regionCode = (await this._ui.prompt<string>("regionCode", "AWS region code:"))!;
                        let regionCode = yield this.promptForLocation();
                        registry = new image_registry_1.AwsPrivateEcrImageRegistry(awsUser.accountId, regionCode);
                        registry.pullRequiresAuth = true;
                    }
                    else {
                        // REGISTRY IN AWS PUBLIC CONTAINER GALLERY
                        // NOT region-based.
                        // NOTE: Your Alias doesnt get created until the first repository is created.
                        // url: `public.ecr.aws/${PUBLIC_REGISTRY_ALIAS}/`
                        // eg:  `public.ecr.aws/e7d8o5e6/`
                        // NOTE: You may use custom or default alias in the url; both are valid.
                        // regUrl = (await this._ui.prompt("regUrl", "Enter the public registry base url"))!;   // eg: public.ecr.aws/e7d8o5e6 
                        let alias = (yield this._ui.prompt("alias", "Alias for your registry:")); // eg: public.ecr.aws/e7d8o5e6 
                        registry = new image_registry_1.AwsPublicEcrImageRegistry(alias);
                    }
                    resolve(registry);
                }
                catch (err) {
                    let errMsg = "Cannot capture image registry: ".concat((_a = err.name) !== null && _a !== void 0 ? _a : '', " ", (_b = err.message) !== null && _b !== void 0 ? _b : '');
                    this.logger.error(errMsg, err.stack);
                    reject(new Error(errMsg));
                }
            }));
        });
    }
    defineCluster(initial, defaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                var _a, _b, _c, _d, _e, _f;
                let output;
                try {
                    const DEFAULT_STARTING_NODE_COUNT = 2;
                    const ORIGINAL_NODE_POOL_NAME = "original";
                    let cluster = {};
                    cluster.provider = this.cloudProvider;
                    cluster.privateOwner = this.codiacUser.tenantCode;
                    // APPLY DEFAULTS FOR THIS CSP
                    let switchedCsp = Boolean(defaults !== undefined && (defaults.provider !== this.cloudProvider));
                    if (defaults === undefined || switchedCsp) {
                        let defaultResult = yield this.genRelayClient.Call.getClusterDefaults({ provider: this.cloudProvider });
                        if (defaultResult.error) {
                            this.logger.warn(`Error retrieving defaults for ${this.cloudProvider} cluster: ${(_a = defaultResult.error.name) !== null && _a !== void 0 ? _a : ""} ${(_b = defaultResult.error.message) !== null && _b !== void 0 ? _b : ""}`);
                        }
                        defaults = (_c = defaultResult.output) !== null && _c !== void 0 ? _c : {}; // fall back to an empty object if we failed, so that we dont keep looking this up on subsequent calls.
                        let assignment = (objVal, srcVal) => Boolean(srcVal === undefined) ? objVal : srcVal;
                        if (switchedCsp) {
                            initial = _.assignWith({}, defaults, cluster, { name: initial.name }, assignment); // Throw out any prior cluster properties bc they were set for a diff provider.
                        }
                        else {
                            initial = _.assignWith({}, defaults, initial, assignment);
                        }
                    }
                    cluster.name = yield this.promptForName(initial === null || initial === void 0 ? void 0 : initial.name);
                    cluster.locationName = yield this.promptForLocation(initial === null || initial === void 0 ? void 0 : initial.locationName);
                    // TODO: Use the method `getIdentityFrom()` from the Codiac AwsAdapter lib to derive this from the Aws primary creds. 
                    // cluster.providerSubscription = (await this._ui.prompt("providerSubscription", "Aws Account Id (ten-digit code): ", true, initial?.providerSubscription))!;
                    // cluster.providerSubscription = await this.promptForAccountId(initial?.providerSubscription);
                    let awsUser = (yield this.getAwsUserInfo(initial.providerSubscription, true));
                    cluster.providerSubscription = awsUser.accountId;
                    cluster.providerGroup = "n/a"; // (await this._ui.prompt("providerGroup", "Resource Group: ", true, cluster.providerGroup || cluster.name))!;
                    let subnet = (yield this._ui.prompt("subnet", "Subnet: ", false, (_d = initial === null || initial === void 0 ? void 0 : initial.subnet) !== null && _d !== void 0 ? _d : codiac_constants_1.CliConstants.CHOICE_VALUE_FOR_AUTOCREATE));
                    cluster.subnet = (subnet === codiac_constants_1.CliConstants.CHOICE_VALUE_FOR_AUTOCREATE) ? undefined : subnet;
                    const mainNodeGroup = yield this.promptForNodeGroup(initial, ORIGINAL_NODE_POOL_NAME, DEFAULT_STARTING_NODE_COUNT);
                    // TODO: Convert to  -->  cluster.nodePools = [mainNodeGroup];
                    cluster.nodeSpec = mainNodeGroup.nodeSpec;
                    cluster.startingNodeCount = mainNodeGroup.startingNodeCount;
                    cluster.nodesMin = mainNodeGroup.nodesMin;
                    cluster.nodesMax = mainNodeGroup.nodesMax;
                    cluster.k8sVersion = yield this.promptForK8sVersion(cluster.locationName, initial === null || initial === void 0 ? void 0 : initial.k8sVersion);
                    cluster.ingressDef = yield this.promptForIngressSpec(initial.ingressDef);
                    let spec = Object.assign({ name: cluster.name, provider: cluster.provider, providerSubscription: cluster.providerSubscription, locationName: cluster.locationName, providerGroup: cluster.providerGroup, nodeCount: cluster.nodeCount, ingressDef: cluster.ingressDef, privateOwner: cluster.privateOwner, nodeSpec: cluster.nodeSpec, startingNodeCount: cluster.startingNodeCount, identitySpec: { type: contracts_1.SecurityAccountTypeEnum.servicePrincipal, name: "" } }, this.createAuditable());
                    spec.k8sVersion = cluster.k8sVersion;
                    if (cluster === null || cluster === void 0 ? void 0 : cluster.nodePools)
                        spec.nodePools = cluster.nodePools;
                    if (cluster.defaultFootprint)
                        spec.defaultFootprint = cluster.defaultFootprint;
                    if (cluster.startingNodeCount)
                        spec.startingNodeCount = cluster.startingNodeCount;
                    if (cluster.subnet)
                        spec.subnet = cluster.subnet;
                    if (cluster.windowsAdmin)
                        spec.windowsAdmin = cluster.windowsAdmin;
                    resolve({ spec: spec, defaults: defaults });
                }
                catch (err) {
                    let errMsg = "Error defining cluster: ".concat((_e = err.name) !== null && _e !== void 0 ? _e : '', " ", (_f = err.message) !== null && _f !== void 0 ? _f : '');
                    this.logger.error(errMsg, err.stack);
                    reject(new Error(errMsg));
                }
            }));
        });
    }
    promptForNodeGroup(initial, nodePoolName, defaultMaxNodes = 3) {
        var _a, _b, _c, _d;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                // const isWindows = await this._ui.promptConfirm("winNodePool", "Is Windows?: ", false);
                const nodeSpec = yield this.promptForNodeSpec(initial === null || initial === void 0 ? void 0 : initial.nodeSpec);
                const nodesMin = (yield this._ui.prompt("startingNodeCount", "Min nodes: ", true, (_a = initial === null || initial === void 0 ? void 0 : initial.nodesMin) !== null && _a !== void 0 ? _a : 1));
                const nodesMax = (yield this._ui.prompt("startingNodeCount", "Max nodes: ", true, (_b = initial === null || initial === void 0 ? void 0 : initial.nodesMax) !== null && _b !== void 0 ? _b : defaultMaxNodes));
                const defaultStarting = Math.ceil(nodesMax + nodesMin / 2); // nearest avg integer
                const startingNodeCount = (yield this._ui.prompt("startingNodeCount", "Starting node count: ", true, (_c = initial === null || initial === void 0 ? void 0 : initial.startingNodeCount) !== null && _c !== void 0 ? _c : defaultStarting));
                let ndef = Object.assign({ name: nodePoolName, clusterName: initial.name, nodeSpec: nodeSpec, nodesMin: nodesMin, nodesMax: nodesMax, startingNodeCount: startingNodeCount }, this.createAuditable());
                // if (isWindows == true) ndef.isWindows = isWindows;
                return ndef;
            }
            catch (err) {
                err.message = "Error defining cluster node pool: ".concat((_d = err.message) !== null && _d !== void 0 ? _d : "(no message available)");
                this.logger.error(err.message, err);
                throw err;
            }
        });
    }
    promptForIngressSpec(current) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let partial = Object.assign({}, current);
            // INTERNAL?
            let choices = []; //Object.keys(IngressExposure).map(k => <PromptChoice>{ name: k, value: k });
            choices.push({ value: ingress_exposure_enum_1.IngressExposure.external, name: ingress_exposure_enum_1.IngressExposure.external.concat(this._styler.dim(" (Accessible from the internet)")) });
            choices.push({ value: ingress_exposure_enum_1.IngressExposure.internal, name: ingress_exposure_enum_1.IngressExposure.internal.concat(this._styler.dim(" (private, inside a network)")) });
            // choices.push({ value: IngressExposure.none, name: IngressExposure.none.concat(this._styler.dim(" (do not install)")) });
            // default to external
            let access = type_safety_utils_1.TypeSafetyUtils.toBoolean(partial.internal) ? ingress_exposure_enum_1.IngressExposure.internal : ingress_exposure_enum_1.IngressExposure.external;
            let keep = false;
            keep = yield this._ui.promptConfirm("internalConfirm", "Ingress: ".concat(this._styler.hilite(access)), true);
            if (!keep) {
                let selected = (yield this._ui.promptSelect("internal", "Ingress: ", choices));
                access = type_safety_utils_1.TypeSafetyUtils.toEnum(ingress_exposure_enum_1.IngressExposure, selected); // assertion ok because the list is limited to valid values.
            }
            if (access == ingress_exposure_enum_1.IngressExposure.internal) {
                partial.internal = true;
            }
            else {
                delete partial.internal;
            }
            // Convert to domain
            let output;
            // HACK: gotta cast (below) bc we're not fully hydrating this thing.  
            // TODO: reconsider putting a partial into the clusterDef
            if (partial.internal == true)
                output = Object.assign(Object.assign({}, output), { internal: partial.internal });
            // if (partial.disableExternal) output = <IngressDef>{ ...output, disableExternal: partial.disableExternal };
            // if (partial.ip_name) output = <IngressDef>{ ...output, ip_name: partial.ip_name };
            return output;
        });
    }
    defineClusterCaptureParams(initial, defaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            throw new Error("Cluster capture not yet implemented for AWS.");
        });
    }
    promptForName(current) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let ultimate;
            let keepName = false;
            if (current != undefined && !_.isEmpty(current)) {
                // if (takeDefaults) {
                //   this._ui.userMessage("Cluster name: ".concat(this._styler.hilite(cluster.name)));
                // } else {
                keepName = yield this._ui.promptConfirm("nameConfirm", "Cluster name: ".concat(this._styler.hilite(current)), true);
                if (keepName)
                    ultimate = current;
                // }
            }
            if (!keepName || ultimate == undefined /* undef check is redundant, but its there for typescript */) {
                do {
                    ultimate = (yield this._ui.prompt("name", "Cluster name: ", true, current));
                } while (_.isEmpty(ultimate));
            }
            return ultimate;
        });
    }
    promptForNodeSpec(defaultValue) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let output;
            try {
                let res = yield this.genRelayClient.Call.getAwsNodeTypes({});
                if (res.error)
                    throw res.error;
                if (res.output == undefined || res.output.length === 0)
                    throw new Error("No node types found.");
                let allNodeTypes = res.output.map(n => n.name);
                // cluster.nodeSpec = (await this._ui.prompt("nodeSpec", "Node type: ", true, defaults?.nodeSpec))!;
                let keepDefault = false;
                if (defaultValue && allNodeTypes.indexOf(defaultValue) >= 0) {
                    keepDefault = yield this._ui.promptConfirm("keepNodeSpec", `Node type: ${this._styler.hilite(defaultValue)} `);
                }
                if (keepDefault === true && defaultValue !== undefined) {
                    output = defaultValue;
                }
                else {
                    let nodeTypeChoices = allNodeTypes.map(x => { return { name: x, value: x }; });
                    // TODO: Fuzzy-search here
                    // output = (await this._ui.promptSelect("nodeSpec", "Node type: ", nodeTypeChoices))!;
                    let fuzzySelector = new cli_common_1.PromptSelectFuzzy(this.logger, this._ui, this._styler);
                    output = (yield fuzzySelector.go("nodeSpec", "Node type: ", false, defaultValue, false, () => tslib_1.__awaiter(this, void 0, void 0, function* () { return nodeTypeChoices; })));
                }
                return output;
            }
            catch (err) {
                throw err;
            }
        });
    }
    promptForLocation(defaultValue) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let output;
            try {
                let regionResult = yield this.genRelayClient.Call.getAwsRegions({});
                if (regionResult.error)
                    throw regionResult.error;
                if (regionResult.output == undefined || regionResult.output.length === 0)
                    throw new Error("No Aws regions found.");
                let allRegions = regionResult.output;
                let keepDefault = false;
                if (defaultValue && allRegions.find(x => x.code === defaultValue)) {
                    keepDefault = yield this._ui.promptConfirm("keepLocation", `Location: ${this._styler.hilite(defaultValue)} `);
                }
                if (keepDefault === true && defaultValue !== undefined) {
                    output = defaultValue;
                }
                else {
                    let byGeoGroup = _.groupBy(allRegions, loc => loc.group);
                    let geoChoices = Object.keys(byGeoGroup);
                    let geo = (yield this._ui.promptSelect("geo", "Geography: ", geoChoices));
                    let regions = _.orderBy(byGeoGroup[geo], ['name']);
                    let regionChoices = regions.map(x => { return { name: `${x.name.padEnd(16, ".")}${x.code.padStart(16, ".")}`, value: x.code }; });
                    output = (yield this._ui.promptSelect("locationName", "Region: ", regionChoices));
                }
                return output;
            }
            catch (err) {
                throw err;
            }
        });
    }
    /** Asks the user whether to keep the default version, and if not presents a select list. */
    promptForK8sVersion(location, defaultK8sVersion) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                var _a, _b;
                let output;
                try {
                    let versResult = yield this.genRelayClient.Call.getAvailableK8sVersions({ provider: this.cloudProvider, location: location });
                    if (versResult.error)
                        throw versResult.error;
                    let k8sVersions = (_b = (_a = versResult.output) === null || _a === void 0 ? void 0 : _a.map(x => x.k8sVersion)) !== null && _b !== void 0 ? _b : [];
                    let keepVersion = false;
                    if (defaultK8sVersion && k8sVersions.indexOf(defaultK8sVersion) > 0) {
                        keepVersion = yield this._ui.promptConfirm("keepVersion", `Kubernetes version: ${this._styler.hilite(defaultK8sVersion)} `);
                    }
                    if (keepVersion === true && defaultK8sVersion !== undefined) {
                        output = defaultK8sVersion;
                    }
                    else {
                        if (k8sVersions.length > 0) {
                            output = (yield this._ui.promptSelect("k8sVersion", "Kubernetes version: ", k8sVersions)); // defaults?.k8sVersion;
                        }
                        else {
                            output = (yield this._ui.prompt("k8sVersion", "Kubernetes version: ", true, defaultK8sVersion));
                        }
                    }
                    resolve(output);
                }
                catch (err) {
                    // this.logger.error(`${err.name ?? ''} ${err.message ?? ''}`, err.stack);
                    reject(err);
                }
            }));
        });
    }
    captureFileStore(accountId, defaults, allowUserInteraction) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let output;
                const cspUser = (yield this.getAwsUserInfo(accountId, true));
                // let region = await this.promptForLocation(/* defaults?.region */);  // TODO: add region/location to FileStoreDef
                let region = ""; // Aws SDK wont give this to us on the s3 bucket.
                let selected = yield this.promptForS3Bucket(cspUser.accountId);
                let instance = {
                    providerSubscriptionId: selected.accountId,
                    resourceId: selected.arn
                };
                output = {
                    name: selected.name,
                    shareName: selected.name,
                    provider: this.cloudProvider,
                    providerSubscriptionId: selected.accountId,
                    location: region,
                    type: contracts_1.FileStoreTypeEnum.awsS3Bucket,
                    instance: instance,
                    created: new Date(Date.now()),
                    createdBy: this.codiacUser.username,
                    modified: new Date(Date.now()),
                    modifiedBy: this.codiacUser.username
                };
                return output;
            }
            catch (err) {
                throw err;
            }
        });
    }
    promptForS3Bucket(accountId) {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let bucketsResult = yield this.genRelayClient.Call.getAwsS3Buckets({ accountId: accountId });
                if (bucketsResult.error) {
                    throw bucketsResult.error;
                }
                else if (bucketsResult.output == undefined || (((_a = bucketsResult.output.length) !== null && _a !== void 0 ? _a : 0) == 0)) {
                    throw new Error("No s3 buckets exist in this Aws account.");
                }
                else {
                    let choices = (_b = bucketsResult.output) === null || _b === void 0 ? void 0 : _b.map(b => ({ name: b.name, value: b.name }));
                    let selectedName = (yield this._ui.promptSelect("s3Bucket", "Existing S3 buckets:", choices));
                    let bucket = (bucketsResult.output.find(x => x.name == selectedName)); // assertion ok bc all choices came from this list
                    return bucket;
                }
            }
            catch (err) {
                throw err;
            }
        });
    }
    createAuditable() {
        let stamp = new Date(Date.now());
        return {
            created: stamp,
            createdBy: this.codiacUser.username,
            modified: stamp,
            modifiedBy: this.codiacUser.username
        };
    }
};
AwsResourceConfigurator = tslib_1.__decorate([
    (0, inversify_1.injectable)(),
    tslib_1.__param(0, (0, inversify_1.inject)(codiac_relay_1.RelayClient)),
    tslib_1.__param(1, (0, inversify_1.inject)(codiac_ops_common_1.UserNameTenantCode)),
    tslib_1.__param(2, (0, inversify_1.inject)(ops_1.INTERFACES_CLI.IUserInputProvider)),
    tslib_1.__param(3, (0, inversify_1.inject)(ops_1.INTERFACES_CLI.IOutputStyler)),
    tslib_1.__param(4, (0, inversify_1.inject)(codiac_common_1.INTERFACES.IBetterLogger)),
    tslib_1.__metadata("design:paramtypes", [codiac_relay_1.RelayClient,
        codiac_ops_common_1.UserNameTenantCode, Object, Object, Object])
], AwsResourceConfigurator);
exports.AwsResourceConfigurator = AwsResourceConfigurator;
//# sourceMappingURL=aws-resource-configurator.js.map