"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const identity_1 = tslib_1.__importDefault(require("lodash/identity"));
const listr_1 = tslib_1.__importDefault(require("listr"));
const yn_1 = tslib_1.__importDefault(require("yn"));
const utils = tslib_1.__importStar(require("./utils"));
const errors_1 = require("./errors");
const logger_1 = require("./logger");
const prompts_1 = require("./prompts");
const constants_1 = require("./constants");
const AZS_COUNT = 3;
const EIP_LIMIT = 5;
exports.getStackName = utils.getServicesStackName;
exports.getServicesStackId = (cloudformation, mycloudStackName) => tslib_1.__awaiter(this, void 0, void 0, function* () {
    const servicesStackName = utils.getServicesStackName(mycloudStackName);
    return utils.getStackId(cloudformation, servicesStackName);
});
exports.configureKYCServicesStack = (conf, { truefaceSpoof, rankOne, client, mycloudStackName, mycloudRegion }) => tslib_1.__awaiter(this, void 0, void 0, function* () {
    const servicesStackName = exports.getStackName(mycloudStackName);
    const servicesStackId = yield exports.getServicesStackId(client.cloudformation, mycloudStackName);
    const exists = !!servicesStackId;
    const bucket = yield conf.getPrivateConfBucket();
    const discoveryObjPath = `${bucket}/discovery/ecs-services.json`;
    if (typeof truefaceSpoof === 'boolean' && typeof rankOne === 'boolean') {
    }
    else {
        const tfVerb = truefaceSpoof ? 'enable' : 'disable';
        const roVerb = rankOne ? 'enable' : 'disable';
        yield prompts_1.confirmOrAbort(`${tfVerb} TrueFace Spoof, ${roVerb} RankOne?`);
    }
    const repoNames = [
        constants_1.REPO_NAMES.nginx,
        truefaceSpoof && constants_1.REPO_NAMES.truefaceSpoof,
        rankOne && constants_1.REPO_NAMES.rankOne,
    ].filter(identity_1.default).join(', ');
    yield prompts_1.confirmOrAbort(`has Tradle given you access to the following ECR repositories? ${repoNames}`);
    const region = mycloudRegion;
    const azsCount = AZS_COUNT;
    const availabilityZones = exists
        ? (yield getServicesStackInfo(client, { stackId: servicesStackId })).availabilityZones
        : yield prompts_1.chooseAZs(client, { region, count: azsCount });
    const usedEIPCount = yield utils.getUsedEIPCount(client.ec2);
    if (!exists && EIP_LIMIT - usedEIPCount < azsCount) {
        yield prompts_1.confirmOrAbort(`WARNING: your account has ${usedEIPCount} Elastic IPs in use in region ${region}.
This stack will create ${azsCount} more. AWS's base limit is 5 per region, so this stack may fail.
You can request a limit increase from AWS here: https://console.aws.amazon.com/support/v1#/case/create?issueType=service-limit-increase&limitType=service-code-vpc
Continue?`);
    }
    const willDeleteStack = !(truefaceSpoof || rankOne);
    if (willDeleteStack) {
        yield prompts_1.confirmOrAbort(`you've disabled all the services disabled, can I delete the KYC services stack?`);
        logger_1.logger.info('deleting KYC services stack: ${servicesStackId}, ETA: 5-10 minutes');
        yield utils.deleteStackAndWait({
            cloudformation: client.cloudformation,
            params: {
                StackName: servicesStackId
            },
        });
        return;
    }
    const enableSSH = yn_1.default(yield prompts_1.confirm('enable SSH into the instances?', false));
    const parameters = availabilityZones.map((az, i) => ({
        ParameterKey: `AZ${(i + 1)}`,
        ParameterValue: az
    }));
    parameters.push({
        ParameterKey: 'S3PathToWriteDiscovery',
        ParameterValue: discoveryObjPath
    });
    if (truefaceSpoof) {
        parameters.push({
            ParameterKey: 'EnableTruefaceSpoof',
            ParameterValue: 'true'
        });
    }
    if (rankOne) {
        parameters.push({
            ParameterKey: 'EnableRankOne',
            ParameterValue: 'true',
        });
    }
    if (enableSSH) {
        const key = yield prompts_1.chooseEC2KeyPair(client.ec2);
        parameters.push({
            ParameterKey: 'KeyName',
            ParameterValue: key
        });
    }
    yield prompts_1.confirmOrAbort(`are you freaking ready?`);
    const tasks = [
        {
            title: 'validate template',
            task: (ctx) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                const params = {
                    StackName: servicesStackId || servicesStackName,
                    Parameters: parameters,
                    TemplateURL: constants_1.SERVICES_STACK_TEMPLATE_URL,
                    Capabilities: ['CAPABILITY_NAMED_IAM']
                };
                let method;
                let waitMethod;
                if (exists) {
                    method = 'updateStackInRegion';
                    waitMethod = 'awaitStackUpdate';
                }
                else {
                    method = 'createStackInRegion';
                    waitMethod = 'awaitStackCreate';
                    params.DisableRollback = true;
                }
                ctx.wait = yield utils[method]({ params, region });
            }),
        },
        {
            title: exists
                ? `update KYC services stack`
                : `create KYC services stack (this will take ~20 minutes)`,
            task: ctx => ctx.wait(),
        },
        {
            title: 'poke MyCloud to pick up update',
            task: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
                yield conf.reboot();
            })
        },
    ];
    yield new listr_1.default(tasks).run();
});
const getServicesStackInfo = (client, { stackId }) => tslib_1.__awaiter(this, void 0, void 0, function* () {
    const { Stacks } = yield client.cloudformation.describeStacks({
        StackName: stackId,
    }).promise();
    const { Outputs } = Stacks[0];
    const availabilityZones = getOutput(Outputs, 'AvailabilityZones').split(',');
    const region = getOutput(Outputs, 'Region');
    return {
        region,
        availabilityZones,
    };
});
const getOutput = (Outputs, key) => Outputs.find(o => o.OutputKey === key).OutputValue;
exports.deleteCorrespondingServicesStack = ({ cloudformation, stackId }) => tslib_1.__awaiter(this, void 0, void 0, function* () {
    const { stackName } = utils.parseStackArn(stackId);
    const servicesStackId = yield exports.getServicesStackId(cloudformation, stackName);
    if (!servicesStackId) {
        throw new errors_1.Errors.NotFound(`services stack for mycloud stack: ${stackId}`);
    }
    logger_1.logger.info(`KYC services stack: deleting ${servicesStackId}, ETA: 5-10 minutes`);
    yield utils.deleteStackAndWait({
        cloudformation,
        params: {
            StackName: servicesStackId
        },
    });
    logger_1.logger.info(`KYC services stack: deleted ${servicesStackId}`);
});
exports.updateKYCServicesStack = (conf, { client, mycloudStackName, mycloudRegion }) => tslib_1.__awaiter(this, void 0, void 0, function* () {
    const { cloudformation } = client;
    const servicesStackName = exports.getStackName(mycloudStackName);
    const servicesStackId = yield exports.getServicesStackId(cloudformation, mycloudStackName);
    if (!servicesStackId) {
        throw new errors_1.Errors.NotFound(`existing kyc-services stack not found`);
    }
    let parameters = yield utils.getStackParameters({ cloudformation, stackId: servicesStackId });
    parameters = parameters
        .filter(p => !p.ParameterKey.endsWith('Image'))
        .map(p => ({
        ParameterKey: p.ParameterKey,
        UsePreviousValue: true,
    }));
    yield prompts_1.confirmOrAbort(`About to update KYC services stack. Are you freaking ready?`);
    const tasks = [
        {
            title: 'validate template',
            task: (ctx) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                const params = {
                    StackName: servicesStackId || servicesStackName,
                    TemplateURL: constants_1.SERVICES_STACK_TEMPLATE_URL,
                    Parameters: parameters,
                    Capabilities: ['CAPABILITY_NAMED_IAM']
                };
                ctx.wait = yield utils.updateStack({ cloudformation, params });
            }),
        },
        {
            title: `update KYC services stack`,
            task: ctx => ctx.wait(),
        },
        {
            title: 'poke MyCloud to pick up update',
            task: () => tslib_1.__awaiter(this, void 0, void 0, function* () {
                yield conf.reboot();
            })
        },
    ];
    yield new listr_1.default(tasks).run();
});
//# sourceMappingURL=kyc-services.js.map