"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");
// import { EnterpriseCriteria, Asset, CabinetClusterRoot, RootMap } from '../../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 AssetUndeploy 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(AssetUndeploy);
                    (_a = this._relayContainer) === null || _a === void 0 ? void 0 : _a.ready$.subscribe(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
                        var _b, _c, _d;
                        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.enterprise, interactionMode)).enterprise;
                            _.remove(rootMap.enterprises, e => e.name != enterprise.name); // trim down to match legacy conditions
                            let enterpriseCode = enterprise.name;
                            // Select the asset(s) to destroy
                            let assetName;
                            if (flags.asset == exports.PROMPT_ME_DESIGNATOR) {
                                let condemned = yield this.promptForAsset(enterpriseCode);
                                assetName = condemned.name;
                            }
                            else if (flags.asset) {
                                let condemned = yield this.promptForAsset(enterpriseCode, flags.asset);
                                assetName = condemned.name;
                            }
                            else {
                                // Update sync codiac with what we've got here in the project.
                                let requestedAssets = yield this.establishAssetContext(enterprise, flags.silent);
                                assetName = requestedAssets[0];
                            }
                            let embellisher;
                            let resulte = yield this._codiacApi.Call.assetWhere({ enterprise: enterpriseCode, asset: assetName, rootMap: rootMap });
                            if (resulte.error != undefined) {
                                throw resulte.error;
                            }
                            else if (resulte.output) {
                                embellisher = this.createAssetVersionEmbellisher(resulte.output);
                            }
                            let cab;
                            [cab] = yield this.rootMapUtils.promptForCabinet(enterpriseCode, rootMap, flags.cabinet, false, embellisher);
                            // let cabinet = await this.establishCabinet(flags.cabinet, true);
                            let cabCntx = { enterprise: cab.enterprise, environment: cab.environment, cabinet: cab.name };
                            // Get the clusterdef so we can get cloud pvd creds
                            let cluster = (_b = cab.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);
                            }
                            this._ui.startSpinner(`Removing ${assetName} from ${cabCntx.cabinet}...`);
                            // let result: Result = await this.relayClient.destroyAssets(cabCntx, [assetName]);
                            let result = yield this.genRelayClient.Call.executeDestroyAssets({ target: cabCntx, assetsNames: [assetName] });
                            this._ui.stopSpinner((result.success === true) ? "SUCCESS" : (result.error) ? "ERROR" : "DONE");
                            if (result.error) {
                                this.logger.error(`Error removing ${assetName} from ${cabCntx.cabinet}: ${result.message}`, result.error);
                                this._ui.userMessage(`Error removing ${assetName} from ${cabCntx.cabinet}: ${result.message}`);
                            }
                            else if (result.success) {
                                this.logger.notice(`Removed ${assetName} from ${cabCntx.cabinet}`);
                                this._ui.userMessage(`Removed ${assetName} from ${cabCntx.cabinet}`);
                            }
                            else {
                                this.logger.warn((_c = result.message) !== null && _c !== void 0 ? _c : `Failed without error removing ${assetName} from ${cabCntx.cabinet}.`, result);
                                this._ui.userMessage((_d = result.message) !== null && _d !== void 0 ? _d : `Failed without error removing ${assetName} from ${cabCntx.cabinet}.`);
                            }
                            resolve();
                        }
                        catch (err) {
                            this.handleError(err);
                            reject(err);
                        }
                        finally {
                            yield this.closeConnections();
                        }
                    }));
                }
                catch (err) {
                    this.handleError(err);
                    reject(err);
                }
                finally {
                    yield this.closeConnections();
                    return;
                }
            }));
        });
    }
    createAssetVersionEmbellisher(deployments) {
        let embellisher = {
            eachEnterprise: (entBranch, ent, rootMap) => {
                // Do nothing
            },
            eachEnviro: (envBranch, env, ent, rootMap) => {
                // Do nothing
            },
            eachCabinet: (cabBranch, cab, env, ent, rootMap) => {
                let dep = deployments.find(d => d.cabinet == cab.name);
                if (dep === null || dep === void 0 ? void 0 : dep.assetVersion) {
                    let version = this._styler.dim("(".concat(dep.assetVersion, ")"));
                    cabBranch.text = cabBranch.text.concat("  ", version);
                }
            },
        };
        return embellisher;
    }
    promptForAsset(enterprise, 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 = { code: enterprise };
                let readResult = yield 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.`);
                }
                // console.log(`${readResult.output[0].assets.length} assets found`)
                // Select from assets in the current enterprise
                let selected;
                let assets = readResult.output[0].assets;
                if (assets.length == 0) {
                    throw new Error(`No assets found`);
                }
                // Take the user's submitted value
                if (assetSearch && assetSearch != exports.PROMPT_ME_DESIGNATOR) {
                    selected = assets.find(a => a.name == assetSearch);
                    if (selected) {
                        // this._ui.userMessage(`Asset: ${this._styler.hilite(assets[0].name)}`);
                    }
                    else {
                        this._ui.userMessage(`The asset you specified was not found.`);
                    }
                }
                if (!selected) {
                    if (assets.length == 1) {
                        let keepAsset = yield this._ui.promptConfirm('assetKeep', `Asset: ${this._styler.hilite(assets[0].name)}`, true);
                        if (keepAsset) {
                            selected = assets[0];
                        }
                        else {
                            this._ui.userMessage("No other assets available. Operation cancelled.");
                            this.exit(1);
                        }
                    }
                    else if (assets.length > 1) {
                        let assSelect = yield this._ui.promptSelect('asset', 'Select an Asset:', assets.map(a => a.name));
                        selected = assets.find(a => a.name == assSelect);
                    }
                }
                if (!selected)
                    throw new Error(`User failed to select a valid asset to destroy.`);
                resolve(selected);
            }
            catch (err) {
                reject(err);
            }
        }));
    }
}
exports.default = AssetUndeploy;
AssetUndeploy.description = 'UN-deploys a given asset from a given cabinet.  Defaults to removing only the pod deployments and leaving the service in place; set the --scorch argument to remove the service.';
AssetUndeploy.flags = {
    // ...commandBase.globalFlags,
    help: core_1.Flags.help({ char: 'h' }),
    enterprise: core_1.Flags.string({ char: 'e', required: false, description: `(optional: required only when asset name is not unique across enterprises) Code (name) of the enterprise to work with` }),
    cabinet: core_1.Flags.string({ char: 'c', required: false, description: `Name of the cabinet from which the asset is to be removed.` }),
    asset: core_1.Flags.string({ char: 'a', required: false, description: `Search string for the name of the asset to destroy (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 destroy  (use ${exports.PROMPT_ME_DESIGNATOR} to be prompted).` }),
    scorch: core_1.Flags.boolean({ char: 's', required: false, description: `(Optional: defaults to false) Destroys the service too, instead of just the deployment and pods.` }),
    silent: core_1.Flags.boolean({ char: 'y', required: false, description: `(Optional: defaults to false) Prevents confirmations of user-values that are remembered from prior runs.` })
};
AssetUndeploy.args = {};
//# sourceMappingURL=undeploy.js.map