"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const YAML = require("yaml");
const tsv = require("tsv");
const jmespath = require("jmespath");
const command_base_exec_1 = require("../../../command-base-exec");
const _ = require("lodash");
const render = require("../../../uilogic/render-methods");
const type_safety_utils_1 = require("../../../uilogic/type-safety-utils");
const codiac_constants_1 = require("../../../codiac-constants");
var OutputFormatsEnumPlus;
(function (OutputFormatsEnumPlus) {
    OutputFormatsEnumPlus["text"] = "text";
    OutputFormatsEnumPlus["tree"] = "tree";
    OutputFormatsEnumPlus["json"] = "json";
    OutputFormatsEnumPlus["yaml"] = "yaml";
    OutputFormatsEnumPlus["tsv"] = "tsv";
    OutputFormatsEnumPlus["csv"] = "csv";
})(OutputFormatsEnumPlus || (OutputFormatsEnumPlus = {}));
class NocClusterList extends command_base_exec_1.CommandBaseExec {
    constructor() {
        super(...arguments);
        this._outputFormat = OutputFormatsEnumPlus.tree;
        this._cabinetCounts = {};
    }
    captureArgs() {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(NocClusterList);
            let partial = {};
            if (flags.enterpriseCode)
                partial.enterprise = flags.enterpriseCode;
            if (flags.output) {
                this._outputFormat = (_a = type_safety_utils_1.TypeSafetyUtils.toEnum(OutputFormatsEnumPlus, flags.output)) !== null && _a !== void 0 ? _a : OutputFormatsEnumPlus.tree;
            }
            else if (!_.isEmpty(flags.query)) {
                this._outputFormat = OutputFormatsEnumPlus.json;
            }
            else {
                this._outputFormat = OutputFormatsEnumPlus.tree;
            }
            if (!_.isEmpty(flags.query) && [OutputFormatsEnumPlus.text, OutputFormatsEnumPlus.tree].includes(this._outputFormat)) {
                throw new Error("Cannot use text or tree output format with the --query parameter.");
            }
            this._query = flags.query;
            return [partial, false];
        });
    }
    buildCandidate_silently(partial, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const clusters = _.sortBy(_.cloneDeep(rootMap.clusters), x => x.name);
            this._cabinetCounts = this.countCabinetsPerCluster(rootMap);
            return { enterprise: partial.enterprise, clusters };
        });
    }
    buildCandidate_interactively(partial, rootMap, takeDefaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const clusters = _.sortBy(_.cloneDeep(rootMap.clusters), x => x.name);
            this._cabinetCounts = this.countCabinetsPerCluster(rootMap);
            return { enterprise: partial.enterprise, clusters };
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("-e", candidate.enterprise);
        if (this._outputFormat !== OutputFormatsEnumPlus.tree)
            cmd.push("-o", this._outputFormat);
        if (this._query)
            cmd.push("-q", this._query);
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        var _a, _b, _c, _d;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let clusters = candidate.clusters;
            if (this._query && !_.isEmpty(this._query.trim())) {
                clusters = jmespath.search(clusters, this._query);
            }
            let output = "";
            switch (this._outputFormat) {
                case OutputFormatsEnumPlus.json:
                    output = JSON.stringify(clusters !== null && clusters !== void 0 ? clusters : [], undefined, 2);
                    this._ui.dataOutput(output);
                    break;
                case OutputFormatsEnumPlus.yaml:
                    output = YAML.stringify(clusters !== null && clusters !== void 0 ? clusters : [], { indent: 2 });
                    this._ui.dataOutput(output);
                    break;
                case OutputFormatsEnumPlus.tsv:
                    tsv.TSV.header = true;
                    output = (_a = tsv.TSV.stringify(clusters !== null && clusters !== void 0 ? clusters : [])) === null || _a === void 0 ? void 0 : _a.trim();
                    this._ui.dataOutput(output);
                    break;
                case OutputFormatsEnumPlus.csv:
                    tsv.TSV.header = true;
                    output = (_b = tsv.CSV.stringify(clusters !== null && clusters !== void 0 ? clusters : [])) === null || _b === void 0 ? void 0 : _b.trim();
                    this._ui.dataOutput(output);
                    break;
                case OutputFormatsEnumPlus.text:
                    output = render.renderStringList(((_c = candidate.clusters) !== null && _c !== void 0 ? _c : []).map(c => this.clusterToString(c)));
                    this._ui.userMessage(output);
                    break;
                case OutputFormatsEnumPlus.tree:
                default:
                    output = render.renderStringTree(((_d = candidate.clusters) !== null && _d !== void 0 ? _d : []).map(c => ({ text: this.clusterToString(c) })));
                    this._ui.userMessage(output);
                    break;
            }
        });
    }
    clusterToString(c) {
        var _a, _b;
        const isLocal = type_safety_utils_1.TypeSafetyUtils.toBoolean(c.thisMachine);
        const localIcon = isLocal ? codiac_constants_1.CliConstants.UTF8_LOCAL.concat(" ") : undefined;
        const qtyCabs = (_a = this._cabinetCounts[c.name]) !== null && _a !== void 0 ? _a : 0;
        const dim1 = isLocal ? `(${c.provider})` : `(${c.provider}, ${c.locationName})`;
        const dim2 = ` (${new Date((_b = c.modified) !== null && _b !== void 0 ? _b : "").toLocaleDateString()}, by ${c.modifiedBy})`;
        return `${this._styler.hilite(c.name)} (${qtyCabs})  ${localIcon !== null && localIcon !== void 0 ? localIcon : ""}${this._styler.dim(dim1)} ${this._styler.dim(dim2)}`;
    }
    countCabinetsPerCluster(rootMap) {
        var _a;
        const counts = {};
        for (const ent of rootMap.enterprises) {
            for (const env of ent.environments) {
                for (const cab of env.cabinets) {
                    if (cab.cluster)
                        counts[cab.cluster] = ((_a = counts[cab.cluster]) !== null && _a !== void 0 ? _a : 0) + 1;
                }
            }
        }
        return counts;
    }
}
exports.default = NocClusterList;
NocClusterList.description = 'Shows the list of clusters.';
NocClusterList.aliases = ["cluster:list"];
NocClusterList.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    enterpriseCode: core_1.Flags.string({ char: 'e', required: false, description: 'Code name of the enterprise to target.' }),
    output: core_1.Flags.string({
        char: 'o',
        description: "Format in which to render the results.",
        options: Object.keys(OutputFormatsEnumPlus),
    }),
    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.' }),
};
NocClusterList.args = {};
NocClusterList.examples = [
    { description: "Simple listing.", command: "<%= config.bin %> <%= command.id %>" },
    { description: "List of cluster names only.", command: "<%= config.bin %> <%= command.id %> -q '[].name'" },
    { description: "Multi-property projection.", command: "<%= config.bin %> <%= command.id %> -q '[].{ name: name, loc: locationName }'" },
    { description: "Filter by name.", command: "<%= config.bin %> <%= command.id %> -q \"[?name == 'my-cluster-on-aws']\"" },
    { description: "Show name and location, sorted by location.", command: "<%= config.bin %> <%= command.id %> -q \"[].{ name: name, loc: locationName } | sort_by(@, &loc)\"" },
    { description: "Export as YAML.", command: "<%= config.bin %> <%= command.id %> -o yaml" },
    { description: "Non-interactive invocation.", command: "<%= config.bin %> <%= command.id %> -e myEnterprise --silent" },
    { description: "Renders the equivalent silent command without executing.", command: "<%= config.bin %> <%= command.id %> -e myEnterprise --to-script" },
];
//# sourceMappingURL=list.js.map