"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const codiac_domain_1 = require("@codiac.io/codiac-domain");
const command_base_exec_tenant_1 = require("../../../command-base-exec-tenant");
const type_safety_utils_1 = require("../../../uilogic/type-safety-utils");
const _ = require("lodash");
class NocClusterInit extends command_base_exec_tenant_1.CommandBaseExecTenant {
    captureArgs() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(NocClusterInit);
            return [{}, false];
        });
    }
    buildCandidate_silently(_partial, _rootMap) {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(NocClusterInit);
            if (!flags.name)
                throw new Error(`Cluster name (--name / -n) is required in silent mode.`);
            const provider = (flags.provider) ? type_safety_utils_1.TypeSafetyUtils.toEnum(codiac_domain_1.CloudProviderEnum, flags.provider) : undefined;
            if (!provider)
                throw new Error(`Cloud provider (--provider / -p) is required in silent mode.`);
            const crit = { privateOwner: (_a = this._userCntx) === null || _a === void 0 ? void 0 : _a.currentTenantCode };
            const projection = { pathsIncluded: ["id", "name", "provider", "providerSubscription", "locationName", "privateOwner", "instance", "ingressDef"], pathsExcluded: [] };
            const readResult = yield this._codiacApi.ClusterDef.tryReadMany(crit, { projection: projection });
            const clusterDefs = ((_b = readResult.output) !== null && _b !== void 0 ? _b : []).map(c => c).filter(c => c.instance != undefined);
            const found = clusterDefs.find(c => c.name === flags.name && c.provider === provider);
            if (!found)
                throw new Error(`Cluster [${flags.name}] not found for provider [${provider}].`);
            return { cluster: { name: found.name, provider: found.provider, providerSubscription: found.providerSubscription, ingressDef: found.ingressDef } };
        });
    }
    buildCandidate_interactively(_partial, _takeDefaults, _rootMap) {
        var _a, _b, _c, _d, _e;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(NocClusterInit);
            const provider = (flags.provider) ? type_safety_utils_1.TypeSafetyUtils.toEnum(codiac_domain_1.CloudProviderEnum, flags.provider) : undefined;
            const adjust = (_a = flags.adjust) !== null && _a !== void 0 ? _a : false;
            const crit = { privateOwner: (_b = this._userCntx) === null || _b === void 0 ? void 0 : _b.currentTenantCode };
            const projection = { pathsIncluded: ["id", "name", "provider", "providerSubscription", "locationName", "privateOwner", "instance", "ingressDef"], pathsExcluded: [] };
            const readResult = yield this._codiacApi.ClusterDef.tryReadMany(crit, { projection: projection });
            let clusterDefs = ((_c = readResult.output) !== null && _c !== void 0 ? _c : []).map(c => c).filter(c => c.instance != undefined);
            if (type_safety_utils_1.TypeSafetyUtils.isEnum(codiac_domain_1.CloudProviderEnum, provider)) {
                clusterDefs = clusterDefs.filter(c => c.provider === provider);
            }
            if (readResult.error === undefined && clusterDefs.length === 0) {
                this._ui.userMessage("No clusters exist with instances to initialize.");
                return undefined;
            }
            let cluster;
            let confirmed = false;
            const candidate = {};
            if (flags.name)
                candidate.name = flags.name;
            do {
                if (readResult.error) {
                    const allPvds = this.cspUiFactory.getAllClusterProviders(this.ioc);
                    const csp = yield this.cspContextualizer.promptForCloudProvider(allPvds, undefined);
                    const name = (yield this._ui.prompt("clusterName", "Enter name of the cluster to initialize:", true));
                    const subx = (yield this._ui.prompt("clusterSubx", (csp === codiac_domain_1.CloudProviderEnum.aws ? "AccountId" : "SubscriptionId").concat(" of the cluster to initialize:"), true));
                    cluster = { name, provider: csp, providerSubscription: subx };
                }
                else {
                    const found = candidate.name ? clusterDefs.find(c => c.name === candidate.name) : undefined;
                    if (found) {
                        cluster = found;
                    }
                    else {
                        const choices = clusterDefs.map(c => ({ name: this.describe(c), value: c.name }));
                        const name = (yield this._ui.promptSelect("clusterName", "Select the cluster to initialize:", choices));
                        const def = clusterDefs.find(c => c.name === name);
                        cluster = def;
                    }
                }
                if (cluster.ingressDef == undefined || _.isEmpty(cluster.ingressDef) || adjust) {
                    const existingIp = (_d = cluster.instance) === null || _d === void 0 ? void 0 : _d.ingressIp;
                    if (existingIp != undefined && ((_e = cluster.ingressDef) === null || _e === void 0 ? void 0 : _e.ingressIp) == undefined) {
                        cluster.ingressDef = Object.assign(Object.assign({}, cluster.ingressDef), { ingressIp: existingIp });
                    }
                    const regCfg = this.cspUiFactory.create(cluster.provider, this.ioc);
                    cluster.ingressDef = yield regCfg.promptForIngressSpec(cluster.ingressDef);
                }
                confirmed = yield this._ui.promptConfirm("confirmInit", `Initialize the cluster: ${this._styler.hilite(this.describe(cluster))} ?`, false);
                if (!confirmed)
                    candidate.name = undefined;
            } while (!confirmed);
            yield this.cspContextualizer.promptForCloudProviderCreds(this.ioc, cluster.provider, undefined, undefined, undefined, cluster.providerSubscription);
            return { cluster: cluster };
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("-n", candidate.cluster.name);
        cmd.push("-p", candidate.cluster.provider);
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { cluster } = candidate;
            const result = yield this.watcher.triggerAndWatch((correlationId, socketId) => this.genRelayClient.Call.clusterInit({ spec: { clusterName: cluster.name, ingressDef: cluster.ingressDef }, socketId, correlationId }));
            if (result.error) {
                const msg = `Error initializing ${cluster.provider} cluster [${cluster.name}]: ${result.message} ${result.error.message || ""}`;
                this.logger.error(msg, result.error);
                this._ui.userMessage(`${this._styler.colorCritical("ERROR!")} ${msg}`);
            }
            else if (!result.success) {
                const msg = `Failed without error initializing ${cluster.provider} cluster [${cluster.name}]: ${result.message}`;
                this.logger.notice(msg, result);
                this._ui.userMessage(`${this._styler.colorCritical("FAILED!")} ${msg}`);
            }
            else {
                const msg = `${this._styler.colorGood("SUCCESS!")} Initialized cluster [${this._styler.hilite(cluster.name)}], ${cluster.provider} subscription [${cluster.providerSubscription}].`;
                this.logger.notice(msg, result);
                this._ui.userMessage(msg);
            }
        });
    }
    describe(cluster) {
        return `${cluster.name} ${this._styler.dim("(" + cluster.provider + (cluster.locationName ? ", " + cluster.locationName : "") + ")")}`;
    }
}
exports.default = NocClusterInit;
NocClusterInit.description = 'Post-create initialization for the cluster (installs the ingress controller service)';
NocClusterInit.aliases = ["cluster:init"];
NocClusterInit.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    name: core_1.Flags.string({ char: 'n', required: false, description: 'Name of the cluster to initialize.' }),
    provider: core_1.Flags.string({ char: 'p', options: Object.keys(codiac_domain_1.CloudProviderEnum), required: false, description: 'Code for the cloud service provider.' }),
    adjust: core_1.Flags.boolean({ required: false, description: 'Invokes interactive user-interface to make changes to the initialization specs even when specs already exist.' }),
    silent: core_1.Flags.boolean({ exclusive: ["echo", "to-script"], description: 'Executes without any user interaction; fails on missing or invalid arguments.' }),
    echo: core_1.Flags.boolean({ exclusive: ["to-script", "silent"], description: 'Renders the equivalent non-interactive command for future use before executing.' }),
    "to-script": core_1.Flags.boolean({ exclusive: ["echo", "silent"], description: 'Renders the equivalent non-interactive command without executing it.' }),
};
NocClusterInit.args = {};
NocClusterInit.examples = [
    { description: "Initialize a cluster interactively.", command: "<%= config.bin %> <%= command.id %>" },
    { description: "Adjust ingress spec on an already-initialized cluster.", command: "<%= config.bin %> <%= command.id %> --adjust" },
    { description: "Non-interactive invocation.", command: "<%= config.bin %> <%= command.id %> -n my-cluster --silent" },
    { description: "Renders the equivalent silent command without executing.", command: "<%= config.bin %> <%= command.id %> -n my-cluster --to-script" },
];
//# sourceMappingURL=init.js.map