"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");
class CabinetList extends command_base_exec_1.CommandBaseExec {
    constructor() {
        super(...arguments);
        this.infrxAliases = ["infrx:cabinet:list", "infrx:cab: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(CabinetList);
            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 ent = candidate.rootMap.enterprises.find(e => e.name === candidate.enterprise);
            if (!ent)
                throw new Error(`Enterprise "${candidate.enterprise}" not found.`);
            const flatList = this.flattenCabinets(candidate.rootMap, candidate.enterprise);
            if (!machineReadable && flatList.length === 0)
                return;
            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, c => c.enterprise, c => c.env, c => c.name);
                    this._ui.userMessage(JSON.stringify(sortedForJson, undefined, 2));
                    break;
                case render_methods_1.OutputFormatsEnum.yaml:
                    const sortedForYaml = this._query ? data : _.sortBy(flatList, c => c.enterprise, c => c.env, c => c.name);
                    this._ui.userMessage(YAML.stringify(sortedForYaml, { indent: 2 }));
                    break;
                case render_methods_1.OutputFormatsEnum.text:
                    const sortedForText = _.sortBy(flatList, c => c.enterprise, c => c.env, c => c.name);
                    const listForText = sortedForText.map(c => {
                        const clusterDesc = ` (${c.cluster.name}, ${c.cluster.provider} ${c.cluster.location})`;
                        return `${c.enterprise}/${c.env}/${this._styler.hilite(c.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.buildCabinetTree(candidate.rootMap, candidate.enterprise)));
                    break;
            }
        });
    }
    flattenCabinets(rootMap, enterprise) {
        var _a, _b, _c;
        const flattened = [];
        const ent = rootMap.enterprises.find(e => e.name === enterprise);
        if (!ent)
            return flattened;
        for (const env of ent.environments) {
            for (const cab of env.cabinets) {
                const 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;
    }
    buildCabinetTree(rootMap, enterprise) {
        const tree = [];
        const ent = rootMap.enterprises.find(e => e.name === enterprise);
        if (!ent)
            return tree;
        const entBranch = { text: `${ent.name} enterprise:` };
        for (const env of _.sortBy(ent.environments, e => e.sequence, e => e.name)) {
            const envBranch = { text: `${env.name}` };
            for (const cab of env.cabinets) {
                const cwg = rootMap.clusters.find(c => c.name === cab.cluster);
                const clusterDesc = cwg ? ` (${cab.cluster}, ${cwg.provider} ${cwg.locationName})` : "";
                if (envBranch.children === undefined)
                    envBranch.children = [];
                envBranch.children.push({ text: `${this._styler.hilite(cab.name)}${this._styler.dim(clusterDesc)} ` });
            }
            if (entBranch.children === undefined)
                entBranch.children = [];
            entBranch.children.push(envBranch);
        }
        tree.push(entBranch);
        return tree;
    }
}
exports.default = CabinetList;
CabinetList.description = 'Shows the list of cabinets and environment.';
CabinetList.aliases = ["cab:list", "infrx:cabinet:list", "infrx:cab:list"];
CabinetList.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    enterprise: core_1.Flags.string({ char: 'e', description: 'The name of the enterprise in which to list cabinets (required only if more than one enterprise exists).' }),
    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.' }),
};
CabinetList.args = {};
CabinetList.examples = [
    { description: "List all cabinets for the current enterprise.", command: "<%= config.bin %> <%= command.id %>" },
    { description: "List cabinets for a specific enterprise.", command: "<%= config.bin %> <%= command.id %> -e myEnterprise" },
    { description: "List cabinet 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