"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");
const codiac_constants_1 = require("../../codiac-constants");
class EnvironmentList 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(EnvironmentList);
            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");
                let envCount = 0;
                rootMap.enterprises.forEach(e => envCount += e.environments.length);
                if ([render_methods_1.OutputFormatsEnum.json, render_methods_1.OutputFormatsEnum.yaml].includes(outputFormat) === false)
                    this._ui.stopSpinner(`found ${envCount}`);
                // RENDER
                let output = "";
                switch (flags.output) {
                    case render_methods_1.OutputFormatsEnum.json:
                        let listForJson = this.FlattenEnviros(rootMap);
                        listForJson = _.sortBy(listForJson, e => e.enterprise, c => c.name);
                        output = JSON.stringify(listForJson, undefined, 2);
                        this._ui.userMessage(output);
                        break;
                    case render_methods_1.OutputFormatsEnum.yaml:
                        let listForYaml = this.FlattenEnviros(rootMap);
                        listForYaml = _.sortBy(listForYaml, c => c.enterprise, c => c.name);
                        output = YAML.stringify(listForYaml, { indent: 2 });
                        this._ui.userMessage(output);
                        break;
                    case render_methods_1.OutputFormatsEnum.text:
                        let flatList = this.FlattenEnviros(rootMap);
                        flatList = _.sortBy(flatList, c => c.enterprise, c => c.name);
                        let listForText = this.buildEnviroListForText(flatList);
                        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 envTree = this.buildEnviroTree(rootMap);
                        let out = render.renderStringTree(envTree); //, this._ui.userMessage);
                        this._ui.userMessage(out);
                        break;
                }
                // if ([OutputFormatsEnum.tree].includes(flags.output)) {
                //   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, flags.output);
                // }
            }
            catch (err) {
                this.handleError(err);
            }
            finally {
                yield this.closeConnections();
                return;
            }
        });
    }
    buildEnviroListForText(flatList) {
        try {
            let listForText = flatList.map(env => {
                let clusterDesc = this.buildEnviroClusterDesc(env.clusters);
                return `${env.enterprise}/${this._styler.hilite(env.name)}${this._styler.dim(clusterDesc)}`;
            });
            return listForText;
        }
        catch (err) {
            throw err;
        }
    }
    /** @param isLastEnviro  Declares that this is the bottom of the environment list, so tree lines should not be added as prefixes to the cluster description.   */
    buildEnviroClusterDesc(clusters, isLastEnviro = false) {
        try {
            let clusterDescs = [];
            for (let cluster of clusters) {
                // Show provider and location
                const isLocal = type_safety_utils_1.TypeSafetyUtils.toBoolean(cluster.thisMachine);
                let localIcon = isLocal ? " ".concat(codiac_constants_1.CliConstants.UTF8_LOCAL) : undefined;
                const thisCluster = cluster.name.concat(localIcon !== null && localIcon !== void 0 ? localIcon : "", " (", cluster.provider, isLocal ? "" : " " + cluster.locationName, ")");
                clusterDescs.push(thisCluster);
            }
            let envSuffix;
            if (clusters.length === 1) {
                // Single (same line)
                const cluster = clusterDescs[0];
                envSuffix = "  ".concat(this._styler.dim(cluster));
            }
            else {
                // Multiple (new line for each prefixed with tree line continuer)
                let treeline = isLastEnviro ? "" : "|";
                envSuffix = clusterDescs.map(cluster => "\n".concat(treeline, "    ", this._styler.dim(cluster))).join("");
            }
            return envSuffix;
        }
        catch (err) {
            throw err;
        }
    }
    // Single-line cluster list (if > 1, doesnt show details, just count)
    // private buildEnviroClusterDesc_oneLineEach(clusters: { name: string, provider: string, locationName: string }[]): string {
    //   try {
    //     let clusterDesc = "";
    //     if (clusters.length > 0) {
    //       if (clusters.length === 1) {
    //         // Only 1, show provider and location
    //         clusterDesc = ` ${clusters[0].name} (${clusters[0].provider}, ${clusters[0].locationName})`
    //       } else {
    //         // Many, list providers of clusters
    //         let byProvider = _.groupBy(clusters, c => c.provider);
    //         let delim = "";
    //         for (let provider in byProvider) {
    //           let qty = byProvider[provider].length;
    //           clusterDesc = clusterDesc.concat(delim, `${qty} on ${provider}`)
    //           delim = ", ";
    //         }
    //         if (clusterDesc != "") clusterDesc = ` (${clusterDesc})`;
    //       }
    //     }
    //     return clusterDesc;
    //   } catch (err) {
    //     throw err;
    //   }
    // }
    buildEnviroTree(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 sorted = _.sortBy(ent.environments, e => e.sequence, e => e.name);
            for (let i = 0; i < sorted.length; i++) {
                let env = sorted[i];
                let clusterDesc = this.buildEnviroClusterDesc((_a = env.clusters) !== null && _a !== void 0 ? _a : [], Boolean(i == (sorted.length - 1)));
                let envBranch = {
                    text: `${this._styler.hilite(env.name)}${clusterDesc} `
                };
                if (entBranch.children === undefined)
                    entBranch.children = [];
                entBranch.children.push(envBranch);
            }
            tree.push(entBranch);
        }
        return tree;
    }
    FlattenEnviros(rootMap) {
        var _a;
        let flattened = [];
        for (let ent of rootMap.enterprises) {
            for (let env of _.sortBy(ent.environments, e => e.sequence, e => e.name)) {
                let flat = {
                    name: env.name,
                    sequence: env.sequence,
                    enterprise: ent.name,
                    thisMachine: env.thisMachine,
                    clusters: (_a = env.clusters) !== null && _a !== void 0 ? _a : []
                };
                if (type_safety_utils_1.TypeSafetyUtils.toBoolean(env.thisMachine))
                    flat.thisMachine = type_safety_utils_1.TypeSafetyUtils.toBoolean(env.thisMachine);
                flattened.push(flat);
            }
        }
        return flattened;
    }
}
exports.default = EnvironmentList;
EnvironmentList.description = 'Shows the list of environments.';
EnvironmentList.aliases = ["enviro:list"];
EnvironmentList.flags = {
    enterprise: core_1.Flags.string({ char: 'e', required: false, description: 'The name of the enterprise to which the environments belong. (defaults to the current enterprise context)' }),
    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.' })
};
EnvironmentList.args = {};
//# sourceMappingURL=list.js.map