"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const YAML = require("yaml");
const jmespath = require("jmespath");
const command_base_exec_1 = require("../../command-base-exec");
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_exec_1.CommandBaseExec {
    constructor() {
        super(...arguments);
        this.infrxAliases = ["infrx:environment:list", "infrx:enviro:list"];
        this._outputFormat = render_methods_1.OutputFormatsEnum.tree;
    }
    captureArgs() {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(EnvironmentList);
            let partial = {};
            if (flags.enterprise)
                partial.enterprise = flags.enterprise;
            this._query = flags.query;
            this._outputFormat = (_a = type_safety_utils_1.TypeSafetyUtils.toEnum(render_methods_1.OutputFormatsEnum, flags.output)) !== null && _a !== void 0 ? _a : render_methods_1.OutputFormatsEnum.tree;
            if (this._query && !flags.output)
                this._outputFormat = render_methods_1.OutputFormatsEnum.json;
            if (this._query && [render_methods_1.OutputFormatsEnum.text, render_methods_1.OutputFormatsEnum.tree].includes(this._outputFormat)) {
                throw new Error("--query is not compatible with --output text or --output tree.");
            }
            return [partial, false];
        });
    }
    buildCandidate_silently(partial, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return { enterprise: partial.enterprise, rootMap };
        });
    }
    buildCandidate_interactively(partial, rootMap, takeDefaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return { enterprise: partial.enterprise, rootMap };
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("-e", candidate.enterprise);
        cmd.push("-o", this._outputFormat);
        if (this._query)
            cmd.push("-q", this._query);
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const machineReadable = [render_methods_1.OutputFormatsEnum.json, render_methods_1.OutputFormatsEnum.yaml].includes(this._outputFormat);
            const flatList = this.flattenEnviros(candidate.rootMap, candidate.enterprise);
            let data = flatList;
            if (this._query) {
                data = jmespath.search(flatList, this._query);
            }
            switch (this._outputFormat) {
                case render_methods_1.OutputFormatsEnum.json:
                    const sortedForJson = this._query ? data : _.sortBy(flatList, e => e.enterprise, e => e.name);
                    this._ui.userMessage(JSON.stringify(sortedForJson, undefined, 2));
                    break;
                case render_methods_1.OutputFormatsEnum.yaml:
                    const sortedForYaml = this._query ? data : _.sortBy(flatList, e => e.enterprise, e => e.name);
                    this._ui.userMessage(YAML.stringify(sortedForYaml, { indent: 2 }));
                    break;
                case render_methods_1.OutputFormatsEnum.text:
                    const sortedForText = _.sortBy(flatList, e => e.enterprise, e => e.name);
                    const listForText = sortedForText.map(env => {
                        const clusterDesc = this.buildEnviroClusterDesc(env.clusters);
                        return `${env.enterprise}/${this._styler.hilite(env.name)}${this._styler.dim(clusterDesc)}`;
                    });
                    this._ui.userMessage(render.renderStringList(listForText));
                    break;
                case render_methods_1.OutputFormatsEnum.tree:
                default:
                    this._ui.userMessage(render.renderStringTree(this.buildEnviroTree(candidate.rootMap, candidate.enterprise)));
                    break;
            }
        });
    }
    flattenEnviros(rootMap, enterprise) {
        var _a;
        const flattened = [];
        const ent = rootMap.enterprises.find(e => e.name === enterprise);
        if (!ent)
            return flattened;
        for (const env of _.sortBy(ent.environments, e => e.sequence, e => e.name)) {
            const flat = {
                name: env.name,
                sequence: env.sequence,
                enterprise: ent.name,
                thisMachine: type_safety_utils_1.TypeSafetyUtils.toBoolean(env.thisMachine),
                clusters: (_a = env.clusters) !== null && _a !== void 0 ? _a : []
            };
            flattened.push(flat);
        }
        return flattened;
    }
    buildEnviroTree(rootMap, enterprise) {
        var _a;
        const tree = [];
        const ent = rootMap.enterprises.find(e => e.name === enterprise);
        if (!ent)
            return tree;
        const entBranch = { text: `${ent.name} enterprise:` };
        const sorted = _.sortBy(ent.environments, e => e.sequence, e => e.name);
        for (let i = 0; i < sorted.length; i++) {
            const env = sorted[i];
            const clusterDesc = this.buildEnviroClusterDesc((_a = env.clusters) !== null && _a !== void 0 ? _a : [], i === sorted.length - 1);
            if (entBranch.children === undefined)
                entBranch.children = [];
            entBranch.children.push({ text: `${this._styler.hilite(env.name)}${clusterDesc} ` });
        }
        tree.push(entBranch);
        return tree;
    }
    buildEnviroClusterDesc(clusters, isLastEnviro = false) {
        const clusterDescs = [];
        for (const cluster of clusters) {
            const isLocal = type_safety_utils_1.TypeSafetyUtils.toBoolean(cluster.thisMachine);
            const localIcon = isLocal ? " ".concat(codiac_constants_1.CliConstants.UTF8_LOCAL) : undefined;
            clusterDescs.push(cluster.name.concat(localIcon !== null && localIcon !== void 0 ? localIcon : "", " (", cluster.provider, isLocal ? "" : " " + cluster.locationName, ")"));
        }
        if (clusters.length === 1) {
            return "  ".concat(this._styler.dim(clusterDescs[0]));
        }
        else {
            const treeline = isLastEnviro ? "" : "|";
            return clusterDescs.map(c => "\n".concat(treeline, "    ", this._styler.dim(c))).join("");
        }
    }
}
exports.default = EnvironmentList;
EnvironmentList.description = 'Shows the list of environments.';
EnvironmentList.aliases = ["enviro:list", "infrx:environment:list", "infrx:enviro:list"];
EnvironmentList.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    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', description: "Format in which to render the results (defaults to tree).", options: [render_methods_1.OutputFormatsEnum.json, render_methods_1.OutputFormatsEnum.yaml, render_methods_1.OutputFormatsEnum.tree, render_methods_1.OutputFormatsEnum.text] }),
    query: core_1.Flags.string({ char: 'q', description: "JMESPath expression to filter or reshape the results (see jmespath.org)." }),
    silent: core_1.Flags.boolean({ exclusive: ["echo", "to-script"], description: 'Executes without any user interaction; fails on missing or invalid arguments.' }),
    echo: core_1.Flags.boolean({ exclusive: ["to-script", "silent"], description: 'Renders the equivalent non-interactive command for future use before executing.' }),
    "to-script": core_1.Flags.boolean({ exclusive: ["echo", "silent"], description: 'Renders the equivalent non-interactive command without executing it.' }),
};
EnvironmentList.args = {};
EnvironmentList.examples = [
    { description: "List all environments for the current enterprise.", command: "<%= config.bin %> <%= command.id %>" },
    { description: "List environments for a specific enterprise.", command: "<%= config.bin %> <%= command.id %> -e myEnterprise" },
    { description: "List environment names only.", command: "<%= config.bin %> <%= command.id %> -q '[].name'" },
    { description: "Export as YAML.", command: "<%= config.bin %> <%= command.id %> -o yaml" },
    { description: "Non-interactive (scripted) invocation.", command: "<%= config.bin %> <%= command.id %> -e myEnterprise --silent" },
];
//# sourceMappingURL=list.js.map