"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PROMPT_ME_DESIGNATOR = void 0;
const tslib_1 = require("tslib");
require("reflect-metadata");
const core_1 = require("@oclif/core");
const _ = require("lodash");
const autocomplete = require("inquirer-autocomplete-prompt");
const contracts_1 = require("../../apis/codiac-api/contracts");
const command_base_enterprise_1 = require("../../command-base-enterprise");
/** The value provided as input that indicates
 * a user's desire to be prompted with a list from which choose the value(s),
 * instead of entering them manually or taking a default. */
exports.PROMPT_ME_DESIGNATOR = "?";
class ConfigDeploy extends command_base_enterprise_1.CommandBaseEnterprise {
    run() {
        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;
                try {
                    this.bootstrap();
                    const { args, flags } = yield this.parse(ConfigDeploy);
                    (_a = this._relayContainer) === null || _a === void 0 ? void 0 : _a.ready$.subscribe(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
                        var _b;
                        try {
                            this._userCntx = yield this.establishTenantContext(this._userCntx);
                            let rootMap = yield this.getRootMap();
                            const interactionMode = this.getInteractionMode(flags.silent, flags.echo, flags['to-script']);
                            let enterprise = (yield this.establishEnterpriseContext(rootMap, flags.enterpriseCode, interactionMode)).enterprise;
                            _.remove(rootMap.enterprises, e => e.name != enterprise.name); // trim down to match legacy conditions
                            let enterpriseCode = enterprise.name;
                            let entRoot = rootMap.enterprises.find(e => e.name == enterpriseCode); // Assertion operator ok bc we already validated the enterprise a few lines above.
                            if (entRoot == undefined) {
                                throw new Error("Enterprise not found.");
                            }
                            else if (!entRoot.assets || entRoot.assets.length == 0) {
                                throw new Error(`The current enterprise [${entRoot.name}] has no assets defined.`);
                            }
                            // Select the asset(s) to deploy
                            let assets;
                            let assetVersions;
                            const helmFilter = (a) => { var _a; return ((_a = a.type) === null || _a === void 0 ? void 0 : _a.toString()) != contracts_1.AssetTypesEnum.helm.toString(); };
                            if (flags.asset == undefined || flags.asset == exports.PROMPT_ME_DESIGNATOR) {
                                let asset = yield this.promptForAsset(entRoot, undefined, helmFilter);
                                assets = [asset];
                                // let selected = await this.promptForVersion(enterpriseCode, asset, flags.version);
                                assetVersions = [{ a: asset.name }];
                            }
                            else if (flags.asset) {
                                let asset = yield this.promptForAsset(entRoot, flags.asset, helmFilter);
                                assets = [asset];
                                // let selected = await this.promptForVersion(enterpriseCode, asset, flags.version);
                                assetVersions = [{ a: asset.name }];
                                // if (!flags.version || flags.version == PROMPT_ME_DESIGNATOR) {
                                // }
                            }
                            else {
                                // -----------------------------------------------------------------
                                // DEVNOTE:  We're skipping this block bc the contextualizer's UI logic is clumsy 
                                //           (doesnt filter out the invalids from the select list, 
                                //           and then after selection the error feels like entrapment, 
                                //           and its err message is wierd).  
                                // -----------------------------------------------------------------
                                // TODO: Revamp the contextualizers:  use a given RootMap, expose means to filter out invalids, react to flags["take-defaults"], render defaulted selection...
                                // -----------------------------------------------------------------
                                // Update sync codiac with what we've got here in the project.
                                let requestedAssets = yield this.establishAssetContext(enterprise, flags.silent);
                                assets = entRoot.assets.filter(a => requestedAssets.includes(a.name));
                                if (assets.length == 0)
                                    throw new Error("No assets found with the given name(s).");
                                assets = assets.filter(a => helmFilter(a));
                                if (assets.length == 0)
                                    throw new Error("No assets found that qualify for deploying configs."); // <-- consider a non-error condition here
                                assetVersions = requestedAssets.map(a => { return { a: a }; });
                                // let versions = await this.declareAssetVersions(requestedAssets, enterpriseCode);
                                // // We've updated Codiac.  Now trigger the deploy.
                                // assetVersions = requestedAssets.map(a => {
                                //   let version = versions.find(v => v.assetName == a);
                                //   return { a: a, v: version ? version.assetVersion : undefined };
                                // });
                            }
                            let cabinet = yield this.establishCabinet(flags.cabinetName);
                            let cabCntx = {
                                enterprise: cabinet.enterpriseCode,
                                environment: cabinet.environment,
                                cabinet: cabinet.name
                            };
                            // Get the clusterdef so we can get cloud pvd creds
                            let cluster = (_b = cabinet.cluster) !== null && _b !== void 0 ? _b : ((rootMap.clusters.length === 1) ? rootMap.clusters[0].name : undefined); // fall back to the one and only.
                            if (cluster === undefined) {
                                this.logger.warn(`Cannot confirm cloud provider credentials: cabinet has no cluster specified. Process will rely on cached credentials.`);
                                // throw new Error(`Cannot determine cloud provider: cabinet has no cluster specified.`);
                            }
                            else {
                                yield this.establishCloudProviderCreds(rootMap, cluster, flags.silent);
                            }
                            this._ui.startSpinner(`Deploying configs to ${cabCntx.environment}/${cabCntx.cabinet}...`);
                            // const response = await this.relayClient.deployConfigsFor(cabCntx, assetVersions);
                            const response = yield this.genRelayClient.Call.postExecuteDeployConfigsFor({ destination: cabCntx, assets: assetVersions });
                            this._ui.stopSpinner("done.");
                        }
                        catch (err) {
                            reject(err);
                        }
                        finally {
                            resolve();
                        }
                    }));
                }
                catch (err) {
                    this.handleError(err);
                    resolve();
                    // reject(err);
                }
                finally {
                    yield this.closeConnections();
                }
            }));
        });
    }
    promptForAsset(enterprise, assetName, assetSearch) {
        return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                // // let ecrit = new EnterpriseCriteria();
                // // ecrit.code = new StringFilter();
                // // ecrit.code.$eq = enterprise;
                // let ecrit = <EnterpriseCriteria>{ code: enterprise };
                // let readResult = await this._codiacApi.Enterprise.tryReadMany(ecrit /* { code: { $eq: enterprise } }  */);
                // if (!readResult.output || readResult.output.length == 0) {
                //   throw new Error(`Could not find enterprise [${enterprise}].`);
                // } else if (!readResult.output[0].assets || readResult.output[0].assets.length == 0) {
                //   throw new Error(`The current enterprise [${enterprise}] has no assets defined.`);
                // }
                if (!enterprise.assets || enterprise.assets.length == 0) {
                    throw new Error(`The current enterprise [${enterprise.name}] has no assets defined.`);
                }
                // console.log(`${readResult.output[0].assets.length} assets found`)
                // Select from assets in the current enterprise
                let assets = enterprise.assets;
                let selected;
                if (assetName && assetName != exports.PROMPT_ME_DESIGNATOR) {
                    assets = assets.filter(a => a.name.startsWith(assetName));
                    if (assets.length == 0) {
                        throw new Error("No assets found with the given name(s).");
                    }
                }
                if (assetSearch) {
                    assets = assets.filter(a => assetSearch(a));
                    if (assets.length == 0) {
                        if (assetName) {
                            throw new Error("That asset does not qualify for deploying configs.");
                        }
                        else {
                            throw new Error("No assets found that qualify for deploying configs."); // <-- consider a non-error condition here.
                        }
                    }
                }
                if (assets.length == 1) {
                    selected = assets[0];
                    this._ui.userMessage("Asset: ".concat(this._styler.hilite(selected.name)));
                }
                else {
                    // (Empty condition was already handled above).
                    // console.log(`${assets.length} assets found`)
                    // let assSelect = await inquirer.prompt({ type: 'list', name: 'asset', message: 'Select an Asset:', choices: assets.map(a => a.name) });
                    let assName = yield this._ui.promptSelect('asset', 'Select an Asset:', assets.map(a => { return { name: a.name, value: a.name }; }));
                    if (!assName)
                        throw new Error(`User failed to select a valid asset for a config deploy.`);
                    selected = assets.find(a => a.name == assName); // Assertion ok bc selections originated from this list.
                }
                resolve(selected);
            }
            catch (err) {
                reject(err);
            }
        }));
    }
}
exports.default = ConfigDeploy;
ConfigDeploy.description = 'Deploys a given asset to a given cabinet.  Defaults to current version.';
ConfigDeploy.dependsOn = ["enterpriseCode", "cabinetName"];
ConfigDeploy.flags = {
    // ...commandBase.globalFlags,
    help: core_1.Flags.help({ char: 'h' }),
    enterpriseCode: core_1.Flags.string({ char: 'e', required: false, description: `Code (name) of the enterprise to deploy` }),
    cabinetName: core_1.Flags.string({ char: 'c', required: false, description: `Target cabinet name you want deploy` }),
    asset: core_1.Flags.string({ char: 'a', required: false, description: `Search string for the name of the asset to deploy (use ${exports.PROMPT_ME_DESIGNATOR} to be prompted).` }),
    version: core_1.Flags.string({ char: 'v', required: false, description: `Search string for the version of the asset to deploy  (use ${exports.PROMPT_ME_DESIGNATOR} to be prompted).` }),
    silent: core_1.Flags.boolean({ char: 'y', dependsOn: ConfigDeploy.dependsOn, required: false, description: `(Optional: defaults to false) Prevents confirmations of user-values that are remembered from prior runs. Requires: ${ConfigDeploy.dependsOn}` })
};
ConfigDeploy.args = {};
//# sourceMappingURL=deploy.js.map