"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_enterprise_1 = require("../../../command-base-enterprise");
const _ = require("lodash");
const render = require("../../../uilogic/render-methods");
// import { OutputFormatsEnum } from '../../../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_enterprise_1.CommandBaseEnterprise {
    run() {
        var _a, _b, _c, _d, _e, _f;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.bootstrap();
            const { args, flags } = yield this.parse(NocClusterList);
            try {
                this._userCntx = yield this.establishTenantContext(this._userCntx);
                let rootMap = yield this.getRootMap();
                let currentEnterprise = (yield this.establishEnterpriseContext(rootMap)).enterprise; // We only need this bc the RootMap requires it.
                _.remove(rootMap.enterprises, e => e.name != currentEnterprise.name); // trim down to match legacy conditions
                let outputFormat;
                if (flags.output) {
                    outputFormat = type_safety_utils_1.TypeSafetyUtils.toEnum(OutputFormatsEnumPlus, flags.output);
                }
                else if (!_.isEmpty(flags.query)) {
                    outputFormat = OutputFormatsEnumPlus.json;
                }
                else {
                    outputFormat = OutputFormatsEnumPlus.tree;
                }
                if (outputFormat == undefined)
                    throw new Error("Unrecognized output format.");
                if (!_.isEmpty(flags.query) && [OutputFormatsEnumPlus.text, OutputFormatsEnumPlus.tree].includes(outputFormat))
                    throw new Error("Cannot use that output type when specifying the query parameter.");
                let omitHeaderRow = false;
                if ([OutputFormatsEnumPlus.tsv, OutputFormatsEnumPlus.csv].includes(outputFormat)) {
                    omitHeaderRow = false; // true; // do this for now, until we add this as a command argument
                }
                // RETRIEVE 
                if ([OutputFormatsEnumPlus.json, OutputFormatsEnumPlus.yaml, OutputFormatsEnumPlus.tsv, OutputFormatsEnumPlus.csv].includes(outputFormat) === false)
                    this._ui.startSpinner("Retrieving");
                let clusterCount = (_b = (_a = rootMap.clusters) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
                if ([OutputFormatsEnumPlus.json, OutputFormatsEnumPlus.yaml, OutputFormatsEnumPlus.tsv, OutputFormatsEnumPlus.csv].includes(outputFormat) === false)
                    this._ui.stopSpinner(`found ${clusterCount}`);
                let clusters = _.cloneDeep(rootMap.clusters);
                clusters = _.sortBy(clusters, x => x.name);
                // APPLY QUERY
                if ((flags.query != undefined) && (!_.isEmpty(flags.query.trim()))) {
                    clusters = jmespath.search(clusters, flags.query);
                }
                // RENDER
                let output = "";
                switch (outputFormat) {
                    case OutputFormatsEnumPlus.json:
                        let listForJson = clusters !== null && clusters !== void 0 ? clusters : [];
                        // listForJson = _.sortBy(listForJson, x => x.name);
                        output = JSON.stringify(listForJson, undefined, 2);
                        this._ui.userMessage(output);
                        break;
                    case OutputFormatsEnumPlus.yaml:
                        let listForYaml = clusters !== null && clusters !== void 0 ? clusters : [];
                        // listForYaml = _.sortBy(listForYaml, x => x.name);
                        output = YAML.stringify(listForYaml, { indent: 2 });
                        this._ui.userMessage(output);
                        break;
                    case OutputFormatsEnumPlus.tsv:
                        // TODO:  Consider d3-dsv instead (https://www.npmjs.com/package/d3-dsv)
                        //        So we can support output that's just a list of strings (eg: from a custom jmespath query).
                        //        eg:  this works but is clumsy:  cod cluster list -q "[].{ loc: locationName } | sort_by(@, &loc)" -o tsv
                        //        eg:  but this returns null:     cod cluster list -q "[].locationName | sort(@)" -o tsv
                        let listForTsv = clusters !== null && clusters !== void 0 ? clusters : [];
                        tsv.TSV.header = !omitHeaderRow;
                        output = (_c = tsv.TSV.stringify(listForTsv)) === null || _c === void 0 ? void 0 : _c.trim();
                        this._ui.userMessage(output);
                        break;
                    case OutputFormatsEnumPlus.csv:
                        // TODO:  Consider d3-dsv instead (https://www.npmjs.com/package/d3-dsv)
                        //        So we can support output that's just a list of strings (eg: from a custom jmespath query).
                        let listForCsv = clusters !== null && clusters !== void 0 ? clusters : [];
                        tsv.TSV.header = !omitHeaderRow;
                        output = (_d = tsv.CSV.stringify(listForCsv)) === null || _d === void 0 ? void 0 : _d.trim();
                        this._ui.userMessage(output);
                        break;
                    case OutputFormatsEnumPlus.text:
                        let flatList = (_e = rootMap.clusters) !== null && _e !== void 0 ? _e : []; // Gotta use the raw tyepsafe record with this output type
                        // flatList = _.sortBy(flatList, c => c.name);
                        let listForText = flatList.map(c => this.clusterToString(c));
                        ;
                        output = render.renderStringList(listForText);
                        this._ui.userMessage(output);
                        break;
                    // TODO:
                    // case OutputFormatsEnum.table:
                    // case OutputFormatsEnum.tsv:
                    //   break;
                    case OutputFormatsEnumPlus.tree:
                    default:
                        let listForTree = (_f = rootMap.clusters) !== null && _f !== void 0 ? _f : []; // Gotta use the raw tyepsafe record with this output type
                        // listForTree = _.sortBy(listForTree, c => c.name);
                        let clusterTree = listForTree.map(c => {
                            return { text: this.clusterToString(c) };
                        });
                        let out = render.renderStringTree(clusterTree); //, this._ui.userMessage);
                        this._ui.userMessage(out);
                        break;
                }
            }
            catch (err) {
                this.handleError(err);
            }
            finally {
                yield this.closeConnections();
                return;
            }
        });
    }
    clusterToString(c) {
        var _a;
        const isLocal = type_safety_utils_1.TypeSafetyUtils.toBoolean(c.thisMachine);
        let localIcon = isLocal ? codiac_constants_1.CliConstants.UTF8_LOCAL.concat(" ") : undefined;
        let dim1 = isLocal ? `(${c.provider})` : `(${c.provider}, ${c.locationName})`;
        let dim2 = ` (${new Date((_a = c.modified) !== null && _a !== void 0 ? _a : "").toLocaleDateString()}, by ${c.modifiedBy})`;
        return `${this._styler.hilite(c.name)}  ${localIcon !== null && localIcon !== void 0 ? localIcon : ""}${this._styler.dim(dim1)} ${this._styler.dim(dim2)}`;
    }
}
exports.default = NocClusterList;
NocClusterList.description = 'Shows the list of clusters.';
NocClusterList.aliases = ["cluster:list"];
NocClusterList.flags = {
    query: core_1.Flags.string({ char: 'q', description: "Jmespath query to filter and format and the results (see https://jmespath.org/ for more info)." }),
    output: core_1.Flags.string({ char: 'o', description: "format in which to render the data.", options: Object.keys(OutputFormatsEnumPlus) }),
    help: core_1.Flags.help({ char: 'h', description: 'Displays the help document for this command.' })
};
NocClusterList.args = {};
NocClusterList.examples = [
    { description: "Simple listing", command: "<%= config.bin %> <%= command.id %>" },
    { description: "List of cluster names", command: "<%= config.bin %> <%= command.id %> -q '[].name'" },
    { description: "Filter by name", command: "<%= config.bin %> <%= command.id %> -q \"[?name == 'my-cluster-on-aws']\"" },
    { description: "Filter by name and show the ingressIp", command: "<%= config.bin %> <%= command.id %> -q \"[?name == 'my-cluster-on-aws'].ingressIp\"" },
    { description: "Show name and location, sorted by location", command: "<%= config.bin %> <%= command.id %> -q \"[].{ name: name, loc: locationName } | sort_by(@, &loc)\"" },
];
//# sourceMappingURL=list.js.map