"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RootMapUiUtils = void 0;
const tslib_1 = require("tslib");
const inversify_1 = require("inversify");
const codiac_common_1 = require("@codiac.io/codiac-common");
const cli_common_1 = require("../cli-common");
const contracts_1 = require("../apis/codiac-api/contracts");
const render = require("./render-methods");
const _ = require("lodash");
const ops_1 = require("../ops");
const type_safety_utils_1 = require("./type-safety-utils");
;
;
;
let RootMapUiUtils = class RootMapUiUtils {
    constructor(_ui, styler, logger) {
        this._ui = _ui;
        this.styler = styler;
        this.logger = logger;
    }
    /** Validates the candidate's current value,
   * prompts the user if necessary,
   * mutates the candidate as needed,
   * and returns the applicable enterprise obj from the RootMap.
   *
   * Throws when unable to assign one,
   * so otherwise, candidate SHALL ALWAYS end up with an enterprise assigned.*/
    promptForEnterprise(candidate, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let ent;
                if (candidate.enterprise != undefined) {
                    // validate the given enterprise
                    if (rootMap.enterprises.length === 0) {
                        throw new Error("No enterprises found. You must create an enterprise to run this command.");
                    }
                    let found = rootMap.enterprises.find(x => x.name === candidate.enterprise);
                    if (found == undefined)
                        candidate.enterprise = undefined;
                }
                if (candidate.enterprise != undefined) {
                    ent = rootMap.enterprises.find(x => x.name === candidate.enterprise); // this assertion operator is ok bc we just validated that its in the list
                }
                else {
                    if (rootMap.enterprises.length === 1) {
                        ent = rootMap.enterprises[0];
                        candidate.enterprise = ent.name; // Auto-select the one-and-only
                    }
                    else {
                        // PROMPT FOR IT
                        let choices = rootMap.enterprises.map(e => e.name);
                        candidate.enterprise = (yield this._ui.promptSelect("enterprise", "Enterprise: ", choices));
                        ent = (rootMap.enterprises.find(x => x.name === candidate.enterprise)); // this assertion operator is ok bc we know its in this list
                    }
                }
                return ent;
            }
            catch (err) {
                throw err;
            }
        });
    }
    /** Returns the ultiamate asset name and the flag telling whether the original user input was changed.
     *
     * @param type Must be pulled from asset record, but may be undefined.  MUST have this set for anything that's not a container service asset.
     * @param renderAutoSelected Writes a line showing the selected asset name when if none was specified and the one-and-only gets autoselected.
    */
    promptForAsset(assets, current, renderAutoSelected = false) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let selected = current;
            let assetType;
            let changed = false;
            if (assets.length === 0) {
                throw new Error("This enterprise has no assets. You must create an asset to run this command.");
            }
            if (selected != undefined) {
                // Drop the current value if its invalid
                let found = assets.find(x => x.name === selected);
                if (found == undefined) {
                    selected = undefined;
                }
                else {
                    assetType = found.type;
                    if (renderAutoSelected)
                        this._ui.userMessage("Asset: ".concat(this.styler.hilite(selected)));
                }
            }
            if (selected == undefined) {
                if (assets.length === 1) {
                    selected = assets[0].name; // Auto-select the one-and-only
                    assetType = assets[0].type;
                    // if (takeDefaults) {
                    if (renderAutoSelected)
                        this._ui.userMessage("Asset: ".concat(this.styler.hilite(selected)));
                    // } else {
                    //   let confirm = await this._ui.promptConfirm("asset", "Asset: ".concat(this.styler.hilite(selected)));
                    //   if (!confirm) {
                    //     throw new Error("Cancelled; no other assets available.  No work was done.");  // TODO: refactor to allow for this kind of cancellation.
                    //   }
                    // }
                }
                else {
                    // PROMPT FOR IT
                    let choices = assets.map(a => { return { name: a.name, value: a.name }; });
                    choices = _.orderBy(choices, x => x.name);
                    let fuzzySelector = new cli_common_1.PromptSelectFuzzy(this.logger, this._ui, this.styler);
                    selected = (yield fuzzySelector.go("asset", "Asset:", false, undefined, false, () => tslib_1.__awaiter(this, void 0, void 0, function* () { return choices; })));
                    assetType = assets.find(a => a.name == selected).type; // Assertion operator ok here because we chose from them
                }
                changed = Boolean(current != undefined);
            }
            return [selected, changed, assetType];
        });
    }
    /** Selects a cabinet from a tree view.
     *
     * @returns Cabinet object from RootMap and the environment name.
     * @param takeDefaults (optional, defaults to false) suppresses confirmation of default values when user has not provided any (but NOT when the user-supplied values were invalid and automatically CHANGED to a default).
     */
    promptForCabinet(enterprise, rootMap, defaultValue, takeDefaults = false, embellisher) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let defaultCabName;
                let selectedCabName;
                // render cab tree with all lines selectable
                let cabTree = this.buildCabinetTree(rootMap, embellisher);
                let choices = this.buildSelectChoicesFrom(cabTree);
                // ISSUES:
                // 0. Remove the freaking lines from the selected value.
                // 1. Remember the last cabinet (user's enterprise context).
                // 2. We should only render the cabinets that actually contain a deployment of the asset (or dim the others and loop back if selected)
                // 3. The picklist should render the cluster (provider, name, location) 
                // 4. PERHAPS?  The version of the asset running in the selected cabinet should get rendered (either in the picklist or after the cab is selected)
                /** If we changed the input they provided, we need their confirmation (whether or not they said takeDefaults)  */
                const CAB_PREFIX = "cabinet|";
                let cabChoices = choices.filter(c => c.value.startsWith(CAB_PREFIX));
                let changedUserInput = false;
                if (cabChoices.length === 0) {
                    throw new Error("No work to do: no cabinets were found");
                }
                else if (cabChoices.length === 1) {
                    if (defaultValue != cabChoices[0].value.slice(CAB_PREFIX.length)) {
                        changedUserInput = !_.isEmpty(defaultValue);
                        defaultValue = cabChoices[0].value.slice(CAB_PREFIX.length);
                        defaultCabName = defaultValue.split("|")[0]; // <-- bc the value is "<cabName>|<isLocal>";
                    }
                }
                let keep = takeDefaults;
                if (defaultValue && Boolean(choices.find(x => x.value === `${CAB_PREFIX}${defaultValue}`)) && (changedUserInput || !takeDefaults)) {
                    keep = yield this._ui.promptConfirm("keepCabinet", `Cabinet: ${this.styler.hilite(defaultCabName)} `); // assertion ok bc defaultCabName travels w defaultValue
                }
                if (keep && defaultValue !== undefined) {
                    selectedCabName = defaultCabName; // assertion ok bc defaultCabName travels w defaultValue
                }
                else {
                    let scope;
                    let target;
                    do {
                        if (scope === "environment") {
                            // we could just filter it down from here...
                        }
                        let selection = (yield this._ui.promptSelect("cabinet", "Cabinet: ", choices, false, false));
                        let parts = selection.split("|");
                        scope = parts[0];
                        target = parts[1];
                    } while (scope !== "cabinet"); // ensure they select a cabinet
                    selectedCabName = target;
                }
                let env = this.deriveEnvironmentFrom(enterprise, selectedCabName, rootMap); // this is fkng stupid.  Put this value into the cab value
                let cabObj = this.getCabinetInfrx(enterprise, env.name, selectedCabName, rootMap);
                // return output;
                return [cabObj, env.name];
            }
            catch (err) {
                throw (err);
            }
        });
    }
    deriveEnvironmentFrom(enterprise, cabinet, rootMap) {
        try {
            let ent = rootMap.enterprises.find(e => e.name === enterprise);
            if (ent === undefined)
                throw new Error(`Cannot find environment: did not recognize enterprise [${enterprise}]`);
            let enviro = ent.environments.find(x => x.cabinets.find(c => c.name === cabinet));
            if (enviro === undefined)
                throw new Error(`Cannot find environment: did not recognize cabinet [${cabinet}]`);
            return enviro;
        }
        catch (err) {
            throw err;
        }
    }
    /** Retrieves the cabinet object from the RootMap. */
    getCabinetInfrx(enterprise, environment, cabinet, rootMap) {
        try {
            let targetEnt = rootMap.enterprises.find(ent => ent.name == enterprise);
            let targetCab = targetEnt
                .environments.find(env => env.name == environment)
                .cabinets.find(c => c.name == cabinet);
            return targetCab;
        }
        catch (err) {
            throw err;
        }
    }
    /** sets each value to "scope|target".
    *
    * @param embellisher  (optional) Adds custom content to each branch in the tree
    * */
    buildCabinetTree(rootMap, embellisher) {
        var _a, _b, _c;
        let tree = [];
        for (let ent of rootMap.enterprises) {
            let entBranch = { text: `${ent.name} enterprise:`, value: `${contracts_1.ScopeLevel.enterprise}|${ent.name}` };
            embellisher === null || embellisher === void 0 ? void 0 : embellisher.eachEnterprise(entBranch, ent, rootMap);
            for (let env of _.sortBy(ent.environments, e => e.sequence, e => e.name)) {
                let envBranch = { text: `${env.name}`, value: `${contracts_1.ScopeLevel.environment}|${env.name}|${(_a = env.thisMachine) !== null && _a !== void 0 ? _a : false}` };
                embellisher === null || embellisher === void 0 ? void 0 : embellisher.eachEnviro(envBranch, env, ent, rootMap);
                for (let cab of env.cabinets) {
                    let cabBranch = {
                        text: `${cab.name}`,
                        value: `${contracts_1.ScopeLevel.cabinet}|${cab.name}|${(_b = cab.thisMachine) !== null && _b !== void 0 ? _b : false}`
                    };
                    embellisher === null || embellisher === void 0 ? void 0 : embellisher.eachCabinet(cabBranch, cab, env, ent, rootMap);
                    if (envBranch.children === undefined)
                        envBranch.children = [];
                    (_c = envBranch.children) === null || _c === void 0 ? void 0 : _c.push(cabBranch);
                }
                if (entBranch.children === undefined)
                    entBranch.children = [];
                entBranch.children.push(envBranch);
            }
            tree.push(entBranch);
        }
        return tree;
    }
    /**  */
    promptForEnviro(rootMap, enterprise, defaultEnviro, takeDefaults = false) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let enviro;
            let ent = rootMap.enterprises.find(e => e.name == enterprise);
            if (ent == undefined)
                throw new Error("Enterprise not found.");
            let choices = ent.environments.map(e => ({ name: this.displayForEnv(e, true, false), value: e.name }));
            // Assemble the requested/default selection
            let defaultValue = defaultEnviro;
            // Enforce a valid default / or use the one-and-only
            let defaultChoice;
            let changedUserInput = false;
            if (choices.length === 1) {
                if (defaultValue != choices[0].value) {
                    changedUserInput = !_.isEmpty(defaultValue);
                    defaultChoice = choices[0];
                }
            }
            else {
                defaultChoice = choices.find(x => x.value === defaultValue);
            }
            let keep = takeDefaults;
            let selection;
            if (defaultChoice && (changedUserInput || !takeDefaults)) {
                keep = yield this._ui.promptConfirm("keepEnviro", `Environment: ${this.styler.hilite(defaultChoice.name)} `);
            }
            if (keep && defaultChoice !== undefined) {
                selection = defaultChoice.value;
            }
            else {
                do {
                    selection = (yield this._ui.promptSelect("enviro", "Environment: ", choices, false, false));
                } while (_.isEmpty(selection)); // ensure they select a valid choice (this is only here bc validator isnt working).  Consider moving this to the ui class!!!
            }
            enviro = ent.environments.find(e => e.name == selection);
            return enviro;
        });
    }
    /**  */
    promptForEnviroCluster(rootMap, enterpriseCode, defaultEnviro, defaultCluster, takeDefaults = false) {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let enviro;
            let cluster;
            let embellisher = {
                eachCluster: () => { },
                eachEnterprise: () => { },
                eachEnviro: (item, env, ent, rm) => {
                    if (env.clusters) {
                        if (env.clusters.length == 1) {
                            item.text = item.text.concat(" ", this.styler.dim(env.clusters[0].name.concat(" (", env.clusters[0].provider, ", ", env.clusters[0].locationName, ")")));
                        }
                        else {
                            item.text = item.text.concat(" ", this.styler.dim("(" + env.clusters.length + " clusters)"));
                        }
                    }
                }
            };
            let envTree = this.buildEnviroClusterTree(rootMap); //, embellisher);
            let choices = this.buildSelectChoicesFrom(envTree);
            // Assemble the requested/default selection
            let defaultValue;
            if (defaultEnviro) {
                // Validate defaults.  Cases:  ent y/n/invalid, env y/n/invalid, clu y/n/invalid
                // We can allow some leeway if there's only one enterprise
                let ents = rootMap.enterprises.filter(e => (enterpriseCode == undefined) || (e.name == enterpriseCode));
                if (ents.length == 1) {
                    let ent = ents[0];
                    let matches = choices.filter(c => c.value.startsWith(ent.name.concat("|", defaultEnviro, "|", defaultCluster !== null && defaultCluster !== void 0 ? defaultCluster : "")));
                    if (matches.length == 1) {
                        defaultValue = matches[0].value;
                    }
                    else if (matches.length > 1) {
                        // ambiguous (multiple clusters w/o specifying): cant set a default selection.
                    }
                }
                else {
                    // if there's more than one enterprise and they didnt specify one, 
                    // then all bets are off for matching against their input.
                    // We cant just match on env/cluster names; there's too much of a risk of writing to the wrong enterprise.  
                    // eg: dev|cluster1 could exist in several enterprises (or have been deleted from their intended enterprise since last they looked). 
                }
            }
            // Enforce a valid default / or use the one-and-only
            let defaultChoice;
            let changedUserInput = false;
            if ((choices.length === 2) && (defaultValue != choices[1].value)) /* length 2 because the first is always the enterprise */ {
                changedUserInput = !_.isEmpty(defaultValue);
                defaultChoice = choices[1];
            }
            else {
                defaultChoice = defaultValue ? choices.find(x => x.value === defaultValue) : undefined;
            }
            let keep = takeDefaults;
            let selection;
            if (defaultChoice && (changedUserInput || !takeDefaults)) {
                keep = yield this._ui.promptConfirm("keepEnviro", `Environment: ${this.styler.hilite(this.trimTreeLines(defaultChoice.name))} `);
            }
            if (keep && defaultChoice !== undefined) {
                selection = defaultChoice.value;
            }
            else {
                let validator = (x) => (!_.isEmpty(x)) || "Please select an environment";
                do {
                    selection = (yield this._ui.promptSelect("enviro", "Environment: ", choices, false, false, validator));
                } while (_.isEmpty(selection)); // ensure they select a valid choice (this is only here bc validator isnt working).  Consider moving this to the ui class!!!
            }
            // Derive entities from selection data
            let parts = selection.split("|");
            let entName = parts.shift();
            if (entName == undefined)
                throw new Error("Error parsing selection data: enterprise was missing."); // this should never happen
            let envName = parts.shift();
            if (envName == undefined)
                throw new Error("Error parsing selection data: environment was missing."); // this should never happen
            // assertion ok here bc choices were built from the same rootmap obj
            let ent = rootMap.enterprises.find(e => e.name == entName);
            enviro = ent.environments.find(e => e.name == envName);
            // CLUSTER SELECTION (if needed)
            let clusterName = parts.shift();
            if (clusterName == undefined) {
                let clusterChoices = (_a = enviro.clusters) === null || _a === void 0 ? void 0 : _a.map(c => ({ name: c.name.concat(this.styler.dim(" (".concat(c.provider, " ", c.locationName, ")"))), value: c.name })); // Assertion ok
                clusterName = (yield this._ui.promptSelect("cluster", "Cluster: ", clusterChoices, false, false));
            }
            cluster = (_b = enviro.clusters) === null || _b === void 0 ? void 0 : _b.find(c => c.name == clusterName);
            return [enviro, cluster];
        });
    }
    displayForEnv(enviro, showClusters = true, hilite = true) {
        let display = hilite ? this.styler.hilite(enviro.name) : enviro.name;
        // assemble cluster desc
        let clusterDesc;
        if (enviro.clusters && enviro.clusters.length > 0) {
            if (enviro.clusters.length == 1) {
                // Just one cluster
                let cluster = enviro.clusters[0];
                clusterDesc = "(".concat(cluster.name, ", ", cluster.provider, " ", cluster.locationName, ")");
            }
            else {
                // more than one cluster
                clusterDesc = enviro.clusters.length.toString().concat(" clusters");
                let providers = _.uniq(enviro.clusters.map(c => c.provider).sort());
                let locations = _.uniq(enviro.clusters.map(c => c.locationName).sort());
                if (providers.length == 1 || locations.length == 1)
                    clusterDesc = clusterDesc.concat(",");
                if (providers.length == 1)
                    clusterDesc = clusterDesc.concat(" ", providers[0]);
                if (locations.length == 1)
                    clusterDesc = clusterDesc.concat(" ", locations[0]);
                clusterDesc = "(".concat(clusterDesc, ")");
            }
        }
        else {
            clusterDesc = "(no cluster)";
        }
        return display.concat(" ", this.styler.dim(clusterDesc));
    }
    displayForEnvCluster(enviro, cluster) {
        return enviro.name.concat(this.styler.dim(" (".concat(cluster.name, ", ", cluster.provider, " ", cluster.locationName, ")")));
    }
    /** Selects a unique "enterprise|enviro|cluster?".
     *
     * @param embellisher  (optional) Adds custom content to each branch in the tree
     * */
    buildEnviroClusterTree(rootMap, embellisher) {
        let tree = [];
        for (let ent of rootMap.enterprises) {
            let entBranch = { text: this.styler.dim(`${ent.name} enterprise:`), value: "" }; // TODO: Make this an invalid selection
            embellisher === null || embellisher === void 0 ? void 0 : embellisher.eachEnterprise(entBranch, ent, rootMap);
            for (let env of _.sortBy(ent.environments, e => e.sequence, e => e.name)) {
                let envBranch = { text: env.name, value: ent.name.concat("|", env.name) };
                // ea enviro
                if (env.clusters == undefined || env.clusters.length == 0) {
                    envBranch.text = this.styler.dim(envBranch.text.concat(" (no cluster)")); // this should never happen, but here for clarity in case of bad data.
                    envBranch.value = ""; // Invalid selection (gotta have a cluster)
                }
                else if (env.clusters.length == 1) {
                    // suffix w the one and only cluster in this enviro, but only if it's one of many clusters in the enterprise
                    if (rootMap.clusters.length > 1) {
                        let cluster = env.clusters[0];
                        envBranch.text = this.displayForEnvCluster(env, cluster);
                    }
                    envBranch.value = envBranch.value.concat("|", env.clusters[0].name);
                }
                else {
                    envBranch.text = env.name.concat(this.styler.dim(" (".concat(env.clusters.length.toString(), " clusters)")));
                }
                embellisher === null || embellisher === void 0 ? void 0 : embellisher.eachEnviro(envBranch, env, ent, rootMap);
                // Commented out bc: selecting from many child clusters can be confusing to the user (who thinks theyre selecting an enviro).  WIll have to drill down after as needed. 
                // // ea cluster (if there's more than one)
                // if ((env.clusters?.length ?? 0) > 1) {
                //   for (let cluster of env.clusters ?? []) {
                //     let clusterBranch: TextValueParent = {
                //       text: cluster.name.concat(this.styler.dim(" (".concat(cluster.provider, " ", cluster.locationName, ")"))),
                //       value: ent.name.concat("|", env.name, "|", cluster.name)
                //     }
                //     embellisher?.eachCluster(clusterBranch, cluster, env, ent, rootMap);
                //     if (envBranch.children === undefined) envBranch.children = [];
                //     envBranch.children?.push(clusterBranch)
                //   }
                // }
                if (entBranch.children === undefined)
                    entBranch.children = [];
                entBranch.children.push(envBranch);
            }
            tree.push(entBranch);
        }
        return tree;
    }
    /** Detemines if the given environment exists within the given enterprise (via rootMap).
     * Hydrates the environment property if environmentName is valid.
     *
     * Mutates and returns the partial entity.
     * Throws any exceptions.
     */
    validateEnviro(partial, rootMap) {
        // Pretty sure we dont need these.  If we do, then absorb this logic into the base class and pass in the enterprise entity.
        let ent = rootMap.enterprises.find(e => e.name == partial.enterprise);
        if (ent == undefined)
            throw new Error("Enterprise not found");
        // Validate environment and cluster pairing
        if (partial.environmentName) {
            partial.environment = ent.environments.find(e => e.name == partial.environmentName);
            if (partial.environment == undefined) {
                delete partial.environment;
                delete partial.environmentName;
            }
            this.validateLocalVsRemoteCluster(partial, rootMap);
        }
        return partial;
    }
    /** THrows on invalid.  Passthru for valid. */
    validateLocalVsRemoteCluster(partial, rootMap) {
        var _a, _b;
        // Validate for local data
        let attachedIsLocal = type_safety_utils_1.TypeSafetyUtils.toBoolean((_a = rootMap.clusters.find(c => c.name == partial.cluster)) === null || _a === void 0 ? void 0 : _a.thisMachine);
        if (type_safety_utils_1.TypeSafetyUtils.toBoolean((_b = partial.environment) === null || _b === void 0 ? void 0 : _b.thisMachine)) {
            if (!attachedIsLocal) {
                throw new Error("You are attempting to attach a remote cluster to a local machine environment.  This environment can only support clusters on this machine.");
            }
        }
        else {
            if (attachedIsLocal) {
                throw new Error("You are attempting to attach a cluster on this machine to a remote environment.  This environment can only support remote clusters.");
            }
        }
        return;
    }
    /** Detemines if the given cluster exists within the given rootMap.
     *
     * Mutates and returns the partial entity.
     * Throws any exceptions.
     */
    validateCluster(partial, rootMap) {
        var _a;
        // Pretty sure we dont need these.  If we do, then absorb this logic into the base class and pass in the enterprise entity.
        let ent = rootMap.enterprises.find(e => e.name == partial.enterprise);
        if (ent == undefined)
            throw new Error("Enterprise not found");
        if (partial.cluster) {
            let cluster = (_a = rootMap.clusters) === null || _a === void 0 ? void 0 : _a.find(x => x.name == partial.cluster);
            if (!cluster)
                delete partial.cluster;
        }
        return partial;
    }
    /** Determines if the given environment exists within the given enterprise (via rootMap),
     * and whether the given cluster exists and is contained within the given environment.
     * An invalid or missing environment invalidates the cluster.
     *
     * Mutates and returns the partial entity.
     * Throws any exceptions.
     */
    validateEnviroCluster(partial, rootMap) {
        var _a;
        partial = this.validateEnviro(partial, rootMap);
        if (partial.environment) {
            if (partial.cluster) {
                let cluster = (_a = partial.environment.clusters) === null || _a === void 0 ? void 0 : _a.find(x => x.name == partial.cluster);
                if (!cluster)
                    delete partial.cluster;
            }
        }
        else {
            delete partial.cluster;
        }
        return partial;
    }
    /** Truncates the string to the given length with an ellipses as suffix */
    ellipsis(maxLength, value) {
        let output = value;
        if (output.length > maxLength) {
            let ellipsis = "..."; // Rather use the ellipsis character but String.fromCharCode(133) is returning a problematic character.
            output = output.slice(0, maxLength - 1 - ellipsis.length).concat(ellipsis);
        }
        return output;
    }
    trimTreeLines(candidate) {
        let rxPattern = /^[│├└─\s]+/;
        return candidate.replace(rxPattern, "").trim();
    }
    buildSelectChoicesFrom(tree) {
        try {
            let choices = [];
            // the value is no good here - need scope and target both available
            render.renderStringTree(tree, (txt, item) => choices.push({ name: txt, value: item.value }));
            // // This is one way to do it
            // for (let item of tree) {
            // 
            //   let thisChoice: PromptChoice = { name: item.text, value: item.text };
            //   choices.push(thisChoice);
            // 
            //   if (item.children && item.children.length > 0) {
            //     let children = this.buildSelectChoicesFrom(item.children);
            //     choices.push(...children);
            //   }
            // }
            return choices;
        }
        catch (err) {
            throw err;
        }
    }
};
RootMapUiUtils = tslib_1.__decorate([
    (0, inversify_1.injectable)(),
    tslib_1.__param(0, (0, inversify_1.inject)(ops_1.INTERFACES_CLI.IUserInputProvider)),
    tslib_1.__param(1, (0, inversify_1.inject)(ops_1.INTERFACES_CLI.IOutputStyler)),
    tslib_1.__param(2, (0, inversify_1.inject)(codiac_common_1.INTERFACES.IBetterLogger)),
    tslib_1.__metadata("design:paramtypes", [Object, Object, Object])
], RootMapUiUtils);
exports.RootMapUiUtils = RootMapUiUtils;
//# sourceMappingURL=rootmap-ui-utils.js.map