"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PrivilegeAbbrevsEnum = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const _ = require("lodash");
const render = require("../../../uilogic/render-methods");
const config_ui_utils_1 = require("../../../uilogic/config-ui-utils");
const contracts_1 = require("../../../apis/codiac-api/contracts");
const command_base_exec_1 = require("../../../command-base-exec");
const type_safety_utils_1 = require("../../../uilogic/type-safety-utils");
var PrivilegeAbbrevsEnum;
(function (PrivilegeAbbrevsEnum) {
    PrivilegeAbbrevsEnum["modify"] = "modify";
    PrivilegeAbbrevsEnum["read"] = "read";
    PrivilegeAbbrevsEnum["none"] = "none";
})(PrivilegeAbbrevsEnum = exports.PrivilegeAbbrevsEnum || (exports.PrivilegeAbbrevsEnum = {}));
class AuthCabinetAllowed extends command_base_exec_1.CommandBaseExec {
    constructor() {
        super(...arguments);
        this.adminOnly = true;
    }
    captureArgs() {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { args, flags } = yield this.parse(AuthCabinetAllowed);
            let partial = {};
            if (flags.enterprise)
                partial.enterprise = flags.enterprise;
            if (flags.environment)
                partial.environment = flags.environment;
            if (flags.cabinet)
                partial.cabinet = flags.cabinet;
            if (flags.role)
                partial.role = flags.role;
            if (flags.privilege) {
                partial.privilege = type_safety_utils_1.TypeSafetyUtils.toEnum(PrivilegeAbbrevsEnum, flags.privilege);
                // switch (flags.privilege) {
                //   case PrivilegeAbbrevsEnum.modify:
                //     partial.privileges = [Privilege.Create, Privilege.Read, Privilege.Update, Privilege.Delete];
                //     break;
                //   case PrivilegeAbbrevsEnum.read:
                //     partial.privileges = [Privilege.Read];
                //     break;
                //   case PrivilegeAbbrevsEnum.none:
                //   default:
                //     partial.privileges = [];
                //     break;
                // }
            }
            // ---------------------------------------------------------------
            // TODO: move everything from here down into the base class
            // ---------------------------------------------------------------
            const interactionMode = (this.pipedInput) ? config_ui_utils_1.InteractionModes.silent : (_b = (_a = undefined !== null && undefined !== void 0 ? undefined : (flags.echo ? config_ui_utils_1.InteractionModes.echo : undefined)) !== null && _a !== void 0 ? _a : (flags["to-script"] ? config_ui_utils_1.InteractionModes.toscript : undefined)) !== null && _b !== void 0 ? _b : (flags.silent ? config_ui_utils_1.InteractionModes.silent : undefined);
            const takeDefaults = flags['take-defaults'];
            return [partial, interactionMode, takeDefaults];
        });
    }
    // /** Throws on invalid */
    // private validate(partial: Partial<IAuthRoleDef>): void {
    //   if (partial.name == undefined || _.isEmpty(partial.name)) throw new Error("Missing name");
    //   let rxName = /^[a-zA-Z][a-zA-Z0-9-]{2,50}$/;
    //   if (!rxName.test(partial.name)) throw new Error("Invalid name: must be 3- to 50-character string of alphanumerics and hyphens, starting with a letter.");
    // }
    buildCandidate_silently(partial, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (partial.enterprise == undefined || _.isEmpty(partial.enterprise))
                throw new Error("Must specify enterprise.");
            if (partial.environment == undefined || _.isEmpty(partial.environment))
                throw new Error("Must specify environment.");
            if (partial.cabinet == undefined || _.isEmpty(partial.cabinet))
                throw new Error("Must specify cabinet.");
            // if (partial.role == undefined || _.isEmpty(partial.role)) throw new Error("Must specify role.");
            // if (partial.privilege == undefined || _.isEmpty(partial.privilege)) throw new Error("Must specify privilege.");
            // if (partial.privileges == undefined) throw new Error("Must specify privileges.");
            let candidate = {
                enterprise: partial.enterprise,
                environment: partial.environment,
                cabinet: partial.cabinet,
                rootMap: rootMap
            };
            if (partial.privilege)
                candidate.privilege = partial.privilege;
            if (partial.role)
                candidate.role = partial.role;
            return candidate;
        });
    }
    buildCandidate_interactively(partial, rootMap, takeDefaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            // TODO: 
            // 1) select an enterprise (if > 1)
            // 2) select a role (render already assigned w rwx or read/modify)
            // 3) multi-select privileges (w existing pre-selected)
            return yield this.buildCandidate_silently(partial, rootMap);
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("--enterprise", candidate.enterprise);
        cmd.push("--environment", candidate.environment);
        cmd.push("--cabinet", candidate.cabinet);
        if (candidate.role)
            cmd.push("--role", candidate.role);
        if (candidate.privilege)
            cmd.push("--privilege", candidate.privilege);
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let ent = candidate.rootMap.enterprises.find(e => e.name == candidate.enterprise);
            if (!ent)
                throw new Error("Enterprise not found.");
            let env = ent.environments.find(e => e.name == candidate.environment);
            if (!env)
                throw new Error("Environment not found.");
            let cab = env.cabinets.find(c => c.name == candidate.cabinet);
            if (!cab)
                throw new Error("Cabinet not found.");
            // Perms on the entity
            let perms = this.permsFrom(cab);
            let cabTree = this.buildPermissionTree(this._styler.hilite(cab.name), perms);
            let envTree = [{ text: env.name, children: cabTree }];
            let entTree = [{ text: ent.name.concat(" enterprise:"), children: envTree }];
            let output = render.renderStringTree(entTree);
            this._ui.userMessage(output);
            return;
        });
    }
    permsFrom(entity) {
        var _a, _b, _c;
        let perms = {};
        (_a = entity.readableBy) === null || _a === void 0 ? void 0 : _a.forEach(r => { if (perms[r] == undefined)
            perms[r] = []; perms[r].push(contracts_1.Privilege.read); });
        (_b = entity.writeableBy) === null || _b === void 0 ? void 0 : _b.forEach(r => { if (perms[r] == undefined)
            perms[r] = []; perms[r].push(contracts_1.Privilege.update); });
        (_c = entity.deleteableBy) === null || _c === void 0 ? void 0 : _c.forEach(r => { if (perms[r] == undefined)
            perms[r] = []; perms[r].push(contracts_1.Privilege.delete); });
        return perms;
    }
    /** constructs a "rwd" string from the given set of privileges. */
    toRwd(privs) {
        let rwd = "";
        if (privs.includes(contracts_1.Privilege.read))
            rwd = rwd.concat("r");
        if (privs.includes(contracts_1.Privilege.update))
            rwd = rwd.concat("w");
        if (privs.includes(contracts_1.Privilege.delete))
            rwd = rwd.concat("d");
        return rwd;
    }
    buildPermissionTree(title, perms) {
        let output = [];
        let root = { text: title, children: [] };
        if (_.isEmpty(perms)) {
            root.children.push({ text: "(admin only)" });
        }
        else {
            for (let role in perms) {
                root.children.push({ text: "(".concat(this._styler.hilite(this.toRwd(perms[role])), ") ", role) });
            }
        }
        return [root];
    }
}
exports.default = AuthCabinetAllowed;
AuthCabinetAllowed.description = 'Shows permissions for each security role on the given cabinet entity.';
AuthCabinetAllowed.aliases = ["auth:cab:allowed"];
AuthCabinetAllowed.examples = [
    '<%= config.bin %> <%= command.id %> -e dev -c spike2',
    '<%= config.bin %> <%= command.id %> --enterprise modeling -e qa -c sprint5'
];
AuthCabinetAllowed.flags = {
    enterprise: core_1.Flags.string({ required: false, description: 'Name of the Enterprise containing the cabinet. (Required only if more than one exists).' }),
    environment: core_1.Flags.string({ char: 'e', required: false, description: 'Name of the Environment containing the cabinet. Required in silent mode.' }),
    cabinet: core_1.Flags.string({ char: 'c', required: false, description: 'Name of the cabinet to view. Required in silent mode.' }),
    // role: Flags.string({ char: 'r', required: false, description: 'Name of the Role being assigned. Required in silent mode.' }),
    // privilege: Flags.string({ char: 'p', required: true, options: Object.keys(PrivilegeAbbrevsEnum), description: 'The permission to assign to the Role. ("modify" infers permission to create, read, update, and delete.  "none" removes any permissions set for the role)' }),
    // TODO: Move these into the base class
    silent: core_1.Flags.boolean({ exclusive: ["echo", "to-script"], description: 'Non-Interactive mode; executes without any user interaction and fails on any missing or invalid arguments.' }),
    echo: core_1.Flags.boolean({ exclusive: ["to-script", "silent"], description: 'Echo interaction mode; renders the equivalent non-interactive cli command for future use before final execution.' }),
    "to-script": core_1.Flags.boolean({ exclusive: ["echo", "silent"], description: 'Toscript interaction mode; renders the equivalent non-interactive cli command WITHOUT any execution.' }),
    "take-defaults": core_1.Flags.boolean({ exclusive: ["silent"], description: "Setting this to true prevents prompting for confirmation on parameters that were passed in or were automatically set to default values (Irrelevant in --silent mode).  This behavior does NOT apply to scenarios that the command needs to override invalid user input; such cases will always prompt for confirmation.  eg: when no argument was provided for file or type, and only one exists, the system will render the autoselected file unless this flag is set." })
};
AuthCabinetAllowed.args = {};
//# sourceMappingURL=allowed.js.map