"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const YAML = require("yaml");
const command_base_enterprise_1 = require("../../command-base-enterprise");
const _ = require("lodash");
const render = require("../../uilogic/render-methods");
const render_methods_1 = require("../../uilogic/render-methods");
const type_safety_utils_1 = require("../../uilogic/type-safety-utils");
class CabinetList extends command_base_enterprise_1.CommandBaseEnterprise {
    run() {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.bootstrap();
            const { args, flags } = yield this.parse(CabinetList);
            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 currentEnterprise = (yield this.establishEnterpriseContext(rootMap, flags.enterprise, interactionMode)).enterprise;
                _.remove(rootMap.enterprises, e => e.name != currentEnterprise.name); // trim down to match legacy conditions
                let outputFormat = (_a = type_safety_utils_1.TypeSafetyUtils.toEnum(render_methods_1.OutputFormatsEnum, flags.output)) !== null && _a !== void 0 ? _a : render_methods_1.OutputFormatsEnum.tree;
                // RETRIEVE 
                if ([render_methods_1.OutputFormatsEnum.json, render_methods_1.OutputFormatsEnum.yaml].includes(outputFormat) === false)
                    this._ui.startSpinner("Retrieving cabinets");
                let cabCount = 0;
                // rootMap.enterprises.forEach(e => e.environments.forEach(nv => cabCount += nv.cabinets.length));
                currentEnterprise.environments.forEach(nv => cabCount += nv.cabinets.length);
                if ([render_methods_1.OutputFormatsEnum.json, render_methods_1.OutputFormatsEnum.yaml].includes(outputFormat) === false)
                    this._ui.stopSpinner(`found ${cabCount}`);
                if (cabCount == 0) {
                    // None found, so if this is human-readable render, just quit and dont render anything else. 
                    // (yaml & json renders need to still render an empty data structure)
                    if ([render_methods_1.OutputFormatsEnum.json, render_methods_1.OutputFormatsEnum.yaml].includes(outputFormat) === false) {
                        return;
                    }
                }
                // RENDER
                let output = "";
                switch (outputFormat) {
                    case render_methods_1.OutputFormatsEnum.json:
                        let listForJson = this.FlattenCabinets(rootMap);
                        listForJson = _.sortBy(listForJson, c => c.enterprise, c => c.env, c => c.name);
                        output = JSON.stringify(listForJson, undefined, 2);
                        this._ui.userMessage(output);
                        break;
                    case render_methods_1.OutputFormatsEnum.yaml:
                        let listForYaml = this.FlattenCabinets(rootMap);
                        listForYaml = _.sortBy(listForYaml, c => c.enterprise, c => c.env, c => c.name);
                        output = YAML.stringify(listForYaml, { indent: 2 });
                        this._ui.userMessage(output);
                        break;
                    case render_methods_1.OutputFormatsEnum.text:
                        let flatList = this.FlattenCabinets(rootMap);
                        flatList = _.sortBy(flatList, c => c.enterprise, c => c.env, c => c.name);
                        let listForText = flatList.map(c => {
                            let clusterDesc = ` (${c.cluster.name}, ${c.cluster.provider} ${c.cluster.location})`;
                            return `${c.enterprise}/${c.env}/${this._styler.hilite(c.name)}${this._styler.dim(clusterDesc)}`;
                        });
                        output = render.renderStringList(listForText);
                        this._ui.userMessage(output);
                        break;
                    // TODO:
                    // case OutputFormatsEnum.table:
                    // case OutputFormatsEnum.tsv:
                    //   break;
                    case render_methods_1.OutputFormatsEnum.tree:
                    default:
                        let cabTree = this.buildCabinetTree(rootMap);
                        let out = render.renderStringTree(cabTree); //, this._ui.userMessage);
                        this._ui.userMessage(out);
                        break;
                }
                // if ([OutputFormatsEnum.tree].includes(outputFormat)) {
                //   let cabTree = this.buildCabinetTree(rootMap);
                //   let out = this.renderStringTree(cabTree); //, this._ui.userMessage);
                //   this._ui.userMessage(out);
                // } else {
                //   let flatList: FlatCabinet[] = this.FlattenCabinets(rootMap);
                //   flatList = _.sortBy(flatList, c => c.enterprise, c => c.env, c => c.name)
                //   this.renderCabinets(flatList, outputFormat);
                // }
            }
            catch (err) {
                this.handleError(err);
            }
            finally {
                yield this.closeConnections();
                return;
            }
        });
    }
    buildCabinetTree(rootMap) {
        var _a;
        let tree = [];
        for (let ent of rootMap.enterprises) {
            let entBranch = { text: `${ent.name} enterprise:` };
            for (let env of _.sortBy(ent.environments, e => e.sequence, e => e.name)) {
                let envBranch = { text: `${env.name}` };
                for (let cab of env.cabinets) {
                    let cwg = rootMap.clusters.find(c => c.name === cab.cluster);
                    let clusterDesc = cwg ? ` (${cab.cluster}, ${cwg.provider} ${cwg.locationName})` : "";
                    let cabBranch = { text: `${this._styler.hilite(cab.name)}${this._styler.dim(clusterDesc)} ` };
                    if (envBranch.children === undefined)
                        envBranch.children = [];
                    (_a = envBranch.children) === null || _a === void 0 ? void 0 : _a.push(cabBranch);
                }
                if (entBranch.children === undefined)
                    entBranch.children = [];
                entBranch.children.push(envBranch);
            }
            tree.push(entBranch);
        }
        return tree;
    }
    FlattenCabinets(rootMap) {
        var _a, _b, _c;
        let flattened = [];
        for (let ent of rootMap.enterprises) {
            for (let env of ent.environments) {
                for (let cab of env.cabinets) {
                    let clus = rootMap.clusters.find(c => c.name === cab.cluster);
                    flattened.push({
                        name: cab.name,
                        enterprise: ent.name,
                        env: env.name,
                        cluster: {
                            name: (_a = clus === null || clus === void 0 ? void 0 : clus.name) !== null && _a !== void 0 ? _a : "undefined",
                            provider: (_b = clus === null || clus === void 0 ? void 0 : clus.provider) !== null && _b !== void 0 ? _b : "undefined",
                            location: (_c = clus === null || clus === void 0 ? void 0 : clus.locationName) !== null && _c !== void 0 ? _c : "undefined"
                        }
                    });
                }
            }
        }
        return flattened;
    }
}
exports.default = CabinetList;
CabinetList.description = 'Shows the list of cabinets and environment.';
CabinetList.aliases = ["cab:list"];
CabinetList.flags = {
    enterprise: core_1.Flags.string({ description: '(required only if more than one enterprise exists) The name of the enterprise in which to list cabinets.' }),
    output: core_1.Flags.string({ char: 'o', default: render_methods_1.OutputFormatsEnum.tree, description: "format in which to render the data.", options: [render_methods_1.OutputFormatsEnum.json, render_methods_1.OutputFormatsEnum.yaml, render_methods_1.OutputFormatsEnum.tree, render_methods_1.OutputFormatsEnum.text] }),
    help: core_1.Flags.help({ char: 'h', description: 'Displays the help document for this command.' })
};
CabinetList.args = {};
//# sourceMappingURL=list.js.map