"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CabinetContents = 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 CabinetContents 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(CabinetContents);
            let partial = {};
            if (flags.enterprise)
                partial.enterprise = flags.enterprise;
            if (flags.cabinet)
                partial.cabinet = flags.cabinet;
            // ---------------------------------------------------------------
            // 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.cabinet == undefined)
                throw new Error("Missing cabinet name.");
            for (let env of ent.environments) {
                let cab = env.cabinets.find(c => c.name == partial.cabinet);
                if (cab != undefined) {
                    partial.environment = env.name;
                    break;
                }
            }
            if (!partial.environment)
                throw new Error("Cabinet not found");
            let candidate = {
                enterprise: partial.enterprise,
                environment: partial.environment,
                cabinet: partial.cabinet
            };
            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); // assertion ok bc ent contextualizer already ran
            if (partial.cabinet != undefined) {
                for (let env of ent.environments) {
                    let cab = env.cabinets.find(c => c.name == partial.cabinet);
                    if (cab != undefined) {
                        partial.environment = env.name;
                        break;
                    }
                }
            }
            if (!partial.environment) { // either missing or invalid command args
                let [cab] = yield this.rootMapUtils.promptForCabinet(ent.name, rootMap, partial.cabinet); // TODO: Embellish with total asset counts 
                partial.cabinet = cab.name;
                partial.environment = cab.environment;
            }
            let candidate = {
                enterprise: partial.enterprise,
                environment: partial.environment,
                cabinet: partial.cabinet // assertion ok, ui gauntlet assured valid or cancel
            };
            return candidate;
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("--enterprise", candidate.enterprise);
        cmd.push("--cabinet", candidate.cabinet);
        // cmd.push("--id", candidate.id)
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        var _a, _b, _c, _d, _e;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            // 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 state = stateResult.output;
                // Tree Render
                this._ui.userMessage("Currently deployed to cabinet ".concat(candidate.enterprise, "/", candidate.environment, "/", this._styler.hilite(candidate.cabinet), ":"));
                this._ui.userMessage(" ");
                let env = state.environmentsAsArray.find(e => e.code == candidate.environment);
                if (env != undefined) {
                    let cab = env.cabinets.find(c => c.name == candidate.cabinet);
                    if ((cab === null || cab === void 0 ? void 0 : cab.version) != undefined) {
                        let entVers = state.enterpriseVersions.find(ev => ev.version == cab.version); // assertion ok bc checked on prev line
                        if (entVers === null || entVers === void 0 ? void 0 : entVers.contents) {
                            // Loose assets
                            for (let aVers of entVers.contents.filter(x => x.entityType == "asset").map(v => v)) {
                                let tagList = (aVers.tags && aVers.tags.length > 0) ? "(".concat((_a = aVers.tags) === null || _a === void 0 ? void 0 : _a.map(t => t.name).join(", "), ")") : "";
                                this._ui.userMessage(aVers.assetName.concat(" ", this._styler.hilite(aVers.version), " ", this._styler.dim(tagList)).trim());
                            }
                            // Products
                            for (let pVers of entVers.contents.filter(x => x.entityType == "product").map(pv => pv)) {
                                let tagList = (pVers.tags && pVers.tags.length > 0) ? "(".concat((_b = pVers.tags) === null || _b === void 0 ? void 0 : _b.map(t => t.name).join(", "), ")") : "";
                                this._ui.userMessage(pVers.productName.concat(" ", this._styler.hilite(pVers.version), " ", this._styler.dim(tagList)).trim());
                                // Product assets
                                let indent = "  ";
                                if (pVers.contents) {
                                    for (let aVers of (_c = pVers.contents) === null || _c === void 0 ? void 0 : _c.filter(x => x.entityType == "asset").map(x => x)) {
                                        let tagList = (aVers.tags && aVers.tags.length > 0) ? "(".concat((_d = aVers.tags) === null || _d === void 0 ? void 0 : _d.map(t => t.name).join(", "), ")") : "";
                                        this._ui.userMessage(indent.concat(aVers.assetName, " ", this._styler.hilite(aVers.version), " ", this._styler.dim(tagList)));
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else {
                throw new Error("unable to retrieve cabinet state".concat(": ", (_e = stateResult.message) !== null && _e !== void 0 ? _e : "no details available"));
            }
        });
    }
    // ===========================================================================================================================
    // ===========================================================================================================================
    // ===========================================================================================================================
    // 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.CabinetContents = CabinetContents;
CabinetContents.description = 'Renders the list of asset versions that are currently deployed to the given cabinet.';
CabinetContents.aliases = ['cab:contents'];
CabinetContents.args = {};
CabinetContents.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)' }),
    cabinet: core_1.Flags.string({ char: 'c', required: false, description: "The name of the cabinet to inspect." }),
    // 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." })
};
CabinetContents.examples = [
    '<%= config.bin %> <%= command.id %>',
    '<%= config.bin %> <%= command.id %> -c dev7',
    '<%= config.bin %> <%= command.id %> -e main -c my-spike',
    { description: "use the `--silent` flag to run this command when there is no user at the console (ie: TTY, ie: in a pipeline)", command: '<%= config.bin %> <%= command.id %> -e main -c my-spike --silent' },
    { description: "Use the `--to-script` flag to create a script file that runs this command", command: '<%= config.bin %> <%= command.id %> -e main -c my-spike --to-script > show-contents.sh' }
];
//# sourceMappingURL=contents.js.map