"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 enterprise_contextualizer_1 = require("../../uilogic/enterprise-contextualizer");
const type_safety_utils_1 = require("../../uilogic/type-safety-utils");
const codiac_constants_1 = require("../../codiac-constants");
class AssetList extends command_base_exec_1.CommandBaseExec {
    constructor() {
        super(...arguments);
        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(AssetList);
            let partial = {};
            if (flags.enterprise)
                partial.enterprise = flags.enterprise;
            if (flags.output) {
                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;
            }
            else if (!_.isEmpty(flags.query)) {
                this._outputFormat = render_methods_1.OutputFormatsEnum.json;
            }
            else {
                this._outputFormat = render_methods_1.OutputFormatsEnum.tree;
            }
            if (!_.isEmpty(flags.query) && [render_methods_1.OutputFormatsEnum.text, render_methods_1.OutputFormatsEnum.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) {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const ent = rootMap.enterprises.find(e => e.name === partial.enterprise);
            if (!ent)
                throw new Error(`Enterprise "${partial.enterprise}" not found.`);
            const assets = ((_a = ent.assets) !== null && _a !== void 0 ? _a : []).map(a => this.flattenAsset(a));
            return { enterprise: partial.enterprise, assets };
        });
    }
    buildCandidate_interactively(partial, rootMap, takeDefaults) {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const ent = rootMap.enterprises.find(e => e.name === partial.enterprise);
            if (!ent)
                throw new Error(`Enterprise "${partial.enterprise}" not found.`);
            const assets = ((_a = ent.assets) !== null && _a !== void 0 ? _a : []).map(a => this.flattenAsset(a));
            return { enterprise: partial.enterprise, assets };
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("-e", candidate.enterprise);
        if (this._outputFormat !== render_methods_1.OutputFormatsEnum.tree)
            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* () {
            let assets = _.sortBy(candidate.assets, a => a.enterprise, a => { var _a; return (_a = a.product) !== null && _a !== void 0 ? _a : " "; }, a => a.name);
            if (this._query && !_.isEmpty(this._query.trim())) {
                assets = jmespath.search(assets, this._query);
            }
            let output = "";
            switch (this._outputFormat) {
                case render_methods_1.OutputFormatsEnum.json:
                    output = JSON.stringify(assets, undefined, 2);
                    this._ui.dataOutput(output);
                    break;
                case render_methods_1.OutputFormatsEnum.yaml:
                    output = YAML.stringify(assets, { indent: 2 });
                    this._ui.dataOutput(output);
                    break;
                case render_methods_1.OutputFormatsEnum.text:
                    output = render.renderStringList(this.buildAssetListForText(assets));
                    this._ui.userMessage(output);
                    break;
                case render_methods_1.OutputFormatsEnum.tree:
                default:
                    output = render.renderStringTree(this.buildAssetTree(assets));
                    this._ui.userMessage(output);
                    break;
            }
        });
    }
    buildAssetListForText(flatList) {
        return flatList.map(asset => {
            let output = this._styler.hilite(asset.name);
            if (asset.product !== undefined)
                output = asset.product.concat("/", output);
            output = asset.enterprise.concat("/", output);
            if (type_safety_utils_1.TypeSafetyUtils.toBoolean(asset.hasIngress)) {
                if (type_safety_utils_1.TypeSafetyUtils.toBoolean(asset.ingressInternal)) {
                    output = output.concat(" ", codiac_constants_1.CliConstants.UTF8_FISHEYE);
                }
                else {
                    output = output.concat(" ", codiac_constants_1.CliConstants.UTF8_CLOUD);
                }
            }
            output = output.concat(this._styler.dim(` (${this.renderAssetDetails(asset)})`));
            return output;
        });
    }
    renderAssetDetails(asset) {
        let details = `port: ${asset.port}`;
        details = details.concat(asset.hasIngress ? ", HasIngress" : ", no ingress");
        if (asset.routedWithoutName === true)
            details = details.concat(", RoutedWithoutName");
        details = details.concat(`, from ${asset.registry}`);
        return details;
    }
    buildAssetTree(assets) {
        let tree = [];
        let byProduct = _.groupBy(assets, a => a.product);
        let entBranch;
        for (let product of Object.keys(byProduct).sort()) {
            let prodAssets = byProduct[product];
            let prodBranch = { text: product };
            for (let asset of _.sortBy(prodAssets, a => a.name)) {
                let text = this._styler.hilite(asset.name);
                if (type_safety_utils_1.TypeSafetyUtils.toBoolean(asset.hasIngress)) {
                    if (type_safety_utils_1.TypeSafetyUtils.toBoolean(asset.ingressInternal)) {
                        text = text.concat(" ", codiac_constants_1.CliConstants.UTF8_FISHEYE);
                    }
                    else {
                        text = text.concat(" ", codiac_constants_1.CliConstants.UTF8_CLOUD);
                    }
                }
                text = text.concat(this._styler.dim(` (${this.renderAssetDetails(asset)})`));
                let assetBranch = { text };
                if (prodBranch.children === undefined)
                    prodBranch.children = [];
                prodBranch.children.push(assetBranch);
                if (entBranch === undefined)
                    entBranch = { text: `Enterprise: ${asset.enterprise}` };
            }
            if (entBranch !== undefined) {
                if (entBranch.children === undefined)
                    entBranch.children = [];
                if (product === "undefined") {
                    if (prodBranch.children)
                        entBranch.children.unshift(...prodBranch.children);
                }
                else {
                    entBranch.children.push(prodBranch);
                }
            }
        }
        if (entBranch !== undefined)
            tree.push(entBranch);
        return tree;
    }
    flattenAsset(a) {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        let flattened = {
            name: a.name,
            code: a.code,
            enterprise: a.enterprise,
            hasIngress: a.hasIngress,
            port: enterprise_contextualizer_1.EnterpriseContextualizer.renderAsCsv(a.port),
            product: a.product,
            type: a.type,
            routedWithoutName: a.routedWithoutName,
            image: (_b = (_a = a.image) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : "undefined",
            registry: (_e = (_d = (_c = a.image) === null || _c === void 0 ? void 0 : _c.registry) === null || _d === void 0 ? void 0 : _d.code) !== null && _e !== void 0 ? _e : "undefined",
            registryProvider: (_h = (_g = (_f = a.image) === null || _f === void 0 ? void 0 : _f.registry) === null || _g === void 0 ? void 0 : _g.provider) !== null && _h !== void 0 ? _h : "undefined"
        };
        if (a.ingressInternal)
            flattened.ingressInternal = a.ingressInternal;
        if (a.allowHttp)
            flattened.allowHttp = a.allowHttp;
        if (a.disableHttps)
            flattened.disableHttps = a.disableHttps;
        return flattened;
    }
}
exports.default = AssetList;
AssetList.description = 'Shows the list of assets in a given enterprise.';
AssetList.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    enterprise: core_1.Flags.string({ char: 'e', required: false, description: 'The name of the enterprise containing the assets being viewed (required if there are more than one).' }),
    output: core_1.Flags.string({
        char: 'o',
        description: "Format in which to render the results.",
        options: ["text", "tree", "json", "yaml"],
    }),
    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.' }),
};
AssetList.args = {};
AssetList.examples = [
    { description: "Simple listing.", command: "<%= config.bin %> <%= command.id %>" },
    { description: "List of asset names only.", command: "<%= config.bin %> <%= command.id %> -q '[].name'" },
    { description: "Multi-property projection.", command: "<%= config.bin %> <%= command.id %> -q '[].{ name: name, product: product }'" },
    { description: "Filter assets with ingress.", command: "<%= config.bin %> <%= command.id %> -q \"[?hasIngress == 'true']\"" },
    { 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