"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AssetObliterate = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const command_base_exec_1 = require("../../command-base-exec");
const config_ui_utils_1 = require("../../uilogic/config-ui-utils");
class AssetObliterate extends command_base_exec_1.CommandBaseExec {
    captureArgs() {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { args, flags } = yield this.parse(AssetObliterate);
            let partial = {};
            if (flags.enterprise)
                partial.enterprise = flags.enterprise;
            if (flags.name)
                partial.name = flags.name;
            if (flags.id)
                partial.id = flags.id;
            // ---------------------------------------------------------------
            // TODO: move everything from here down into the base class
            // ---------------------------------------------------------------
            const interactionMode = (this.pipedInput) ? config_ui_utils_1.InteractionModes.silent : (_b = (_a = undefined !== null && undefined !== void 0 ? undefined : (flags.echo ? config_ui_utils_1.InteractionModes.echo : undefined)) !== null && _a !== void 0 ? _a : (flags["to-script"] ? config_ui_utils_1.InteractionModes.toscript : undefined)) !== null && _b !== void 0 ? _b : (flags.silent ? config_ui_utils_1.InteractionModes.silent : undefined);
            // const takeDefaults = flags['take-defaults'];
            return [partial, interactionMode, false];
        });
    }
    buildCandidate_silently(partial, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let ent = rootMap.enterprises.find(e => e.name == partial.enterprise);
            if (!ent)
                throw new Error("Enterprise not found."); // <-- todo: move this up to the base class and pass in the enterprise object.
            if (partial.name == undefined)
                throw new Error("Missing asset name.");
            let asset = ent.assets.find(a => a.name == partial.name);
            if (!asset)
                throw new Error("Asset not found");
            let candidate = {
                enterprise: partial.enterprise,
                name: asset.name,
                id: asset.id // <-- assertion ok bc its necessarily an existing record
            };
            return candidate;
        });
    }
    buildCandidate_interactively(partial, rootMap, takeDefaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let ent = rootMap.enterprises.find(e => e.name == partial.enterprise);
            if (!ent) {
                ent = yield this.rootMapUtils.promptForEnterprise(partial, rootMap);
                partial.enterprise = ent.name;
            }
            let assetChanged;
            let assetType;
            [partial.name, assetChanged, assetType] = yield this.rootMapUtils.promptForAsset(ent.assets, partial.name);
            let asset = ent.assets.find(a => a.name == partial.name);
            if (!asset)
                throw new Error("Asset not found"); // <-- this will never happen - it's just for type safety
            let candidate = {
                enterprise: partial.enterprise,
                name: asset.name,
                id: asset.id // <-- assertion ok bc its necessarily an existing record
            };
            // Check whether it's already deployed before putting up the big warning
            let stateResult = yield this._codiacApi.Call.getDeployedState({ enterprise: candidate.enterprise, noCacheRead: true });
            if (stateResult.success == true && (stateResult.output != undefined)) {
                let cabs = this.assetWhere(asset, stateResult.output); // TODO: Call relay api for this
                if (cabs != undefined && cabs.length > 0) {
                    throw new Error("Asset ".concat("[", asset.name, "]", " cannot be deleted because it is currently deployed to [", cabs.map(x => x.cabinet).join(", "), "]"));
                }
            }
            console.clear();
            this._ui.userMessage(this._styler.colorWarning("/ / / / / / / / / CAUTION!! / / / / / / / / / / / /").concat("\n", "You are about to completely ", this._styler.colorCritical("OBLITERATE"), " ", this._styler.bold(candidate.name), "", "\n", "and all of its associated data in Codiac!", "\n", this._styler.colorWarning("/ / / / / / / / / / / / / / / / / / / / / / / / / /")));
            // let keep = await this._ui.promptConfirm("confirmDelete", "Are you sure? (ctrl-C to cancel)", false);
            // if (!keep) {
            //   this._ui.userMessage("Operation Cancelled.  No work was done.");
            //   this.exit(0);
            // }
            let passPhrase = "yes please erase ".concat(asset.name, " from codiac");
            let confirmation;
            this._ui.userMessage("To confirm, please type: ".concat(this._styler.hilite(passPhrase)));
            while (confirmation == undefined || confirmation != passPhrase) {
                confirmation = yield this._ui.prompt("confirmDelete", "(CTRL-C to cancel)", true);
            }
            return candidate;
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("--enterprise", candidate.enterprise);
        cmd.push("--name", candidate.name);
        // cmd.push("--id", candidate.id)
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let result = yield this._codiacApi.Asset.tryDelete(candidate);
            if (result.error != undefined) {
                throw result.error;
            }
            else if (result.success == true) {
                this._ui.userMessage((_a = result.message) !== null && _a !== void 0 ? _a : "Successfully obliterated asset ".concat("[", candidate.name, "]"));
            }
            else {
                this._ui.userMessage((_b = result.message) !== null && _b !== void 0 ? _b : "Asset record for ".concat("[", candidate.name, "]", " was already deleted."));
            }
        });
    }
    // ===========================================================================================================================
    // ===========================================================================================================================
    // ===========================================================================================================================
    // TODO: Move these methods upstream to a new API endpoint for assetWhere
    /** Retreives the list of cabinets in which the given asset is currently deployed.
     * Throws any exceptions. */
    assetWhere(asset, deployedState) {
        try {
            let cabs;
            for (let env of deployedState.environmentsAsArray) {
                for (let cab of env.cabinets) {
                    if (cab.version && cab.version.trim() != "") {
                        let entVer = deployedState.enterpriseVersions.find(v => v.version == cab.version);
                        const found = entVer ? this.enterpriseVersionContains(asset, entVer) : undefined;
                        if (found && found.trim() != "") {
                            if (!cabs)
                                cabs = [];
                            cabs.push({ enterprise: asset.enterprise, environment: env.code, cabinet: cab.name, assetVersion: found });
                        }
                    }
                }
            }
            return cabs;
        }
        catch (err) {
            throw err;
        }
    }
    /** Determines whether the given asset is part of the given enterprise version,
     * by returning the version of the asset (or undefined if not found).
     */
    enterpriseVersionContains(asset, entVer) {
        var _a;
        if (entVer === null || entVer === void 0 ? void 0 : entVer.contents) {
            // DEVNOTE:  We could check asset.product to see if its part of a product, 
            // but these version configs are historical and therefore may not reflect the latest state of the product definition.
            // Thus we need to recurse for both loose assets and product contents
            // loose asset
            let found = entVer.contents.find(x => x.entityType == "asset" && x.assetName == asset.name);
            if (!found) {
                // asset in a product
                for (let prodVer of entVer.contents.filter(v => v.entityType == "product")) {
                    found = (_a = prodVer.contents) === null || _a === void 0 ? void 0 : _a.find(x => x.entityType == "asset" && x.assetName == asset.name);
                    if (found)
                        break;
                }
            }
            return found === null || found === void 0 ? void 0 : found.version;
        }
        else {
            return undefined;
        }
    }
}
exports.AssetObliterate = AssetObliterate;
AssetObliterate.description = 'Performs a full cascading delete of the given asset and all of its related data in Codiac (eg: versions, probes, configs, tags...). NOTE: This command does NOT delete anything from the image registry.  NOTE: To obliterate an asset, you must first remove it from all cabinets; this command will not obliterate any asset that is currently deployed.';
AssetObliterate.args = {};
AssetObliterate.flags = {
    enterprise: core_1.Flags.string({ char: 'e', required: false, description: 'The name of the enterprise in which to create this asset. (defaults to the current enterprise context)' }),
    name: core_1.Flags.string({ char: 'n', required: false, description: "The name of the asset to obliterate." }),
    // id: Flags.string({ required: false, description: "The system id of the enterprise asset to obliterate." }),
    // TODO: Move these into the base class
    silent: core_1.Flags.boolean({ exclusive: ["echo", "to-script"], dependsOn: ["name"], description: 'Non-Interactive mode; executes without any user interaction and fails on any missing or invalid arguments.' }),
    echo: core_1.Flags.boolean({ exclusive: ["to-script", "silent"], description: 'Echo interaction mode; renders the equivalent non-interactive cli command for future use before final execution.' }),
    "to-script": core_1.Flags.boolean({ exclusive: ["echo", "silent"], description: 'Toscript interaction mode; renders the equivalent non-interactive cli command WITHOUT any execution.' })
    // "take-defaults": Flags.boolean({ exclusive: ["silent"], description: "Setting this to true prevents prompting for confirmation on parameters that were passed in or were automatically set to default values (Irrelevant in --silent mode).  This behavior does NOT apply to scenarios that the command needs to override invalid user input; such cases will always prompt for confirmation.  eg: when no argument was provided for file or type, and only one exists, the system will render the autoselected file unless this flag is set." })
};
AssetObliterate.examples = [
    '<%= config.bin %> <%= command.id %>',
    '<%= config.bin %> <%= command.id %> -n my-api',
    '<%= config.bin %> <%= command.id %> -e main -n my-api',
];
//# sourceMappingURL=obliterate.js.map