"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const _ = require("lodash");
const cli_common_1 = require("../../cli-common");
const read_stdin_1 = require("../../read-stdin");
const config_ui_utils_1 = require("../../uilogic/config-ui-utils");
const user_context_loader_1 = require("../../user-context-loader");
const uilogic_1 = require("../../uilogic");
const bootstrapper_for_auth_dmz_commands_1 = require("../../bootstrapper-for-auth-dmz-commands");
class AuthRegister extends cli_common_1.commandBase {
    get authClient() {
        if (this.__authClient === undefined) {
            this.__authClient = this.ioc.get(uilogic_1.INTERFACES_CLI_ENTERPRISE.IAuthClient);
        }
        return this.__authClient;
    }
    bootstrap() {
        bootstrapper_for_auth_dmz_commands_1.BootstrapperForAuthDmzCommands.bootstrap(this.ioc, this);
    }
    run() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.bootstrap();
            try {
                let [partial, interactionMode, takeDefaults] = yield this.captureArgs();
                let candidate = yield this.buildCandidate_silently(partial);
                yield this.execute(candidate);
            }
            catch (err) {
                this.handleError(err);
            }
        });
    }
    captureArgs() {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { args, flags } = yield this.parse(AuthRegister);
            let partial = {
                newUser: true
            };
            if (flags.email)
                partial.userName = flags.email;
            if (flags.company)
                partial.tenantName = flags.company;
            if (flags.companyCode)
                partial.tenantCode = flags.companyCode;
            if (flags.firstName)
                partial.firstName = flags.firstName;
            if (flags.lastName)
                partial.lastName = flags.lastName;
            if (flags.passwordIn === true) {
                partial.password = yield (0, read_stdin_1.default)();
            }
            else {
                if (flags.password)
                    partial.password = flags.password;
            }
            // this is how csp/login does it...
            // let clientSecret = await readStdin();
            // if (_.isEmpty(clientSecret) && (flags.silent !== true)) {
            //   clientSecret = await this._ui.promptPassword("clientSecret", "Client Secret: ");
            // }
            // ---------------------------------------------------------------
            // 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];
        });
    }
    buildCandidate_silently(partial) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            // Assemble candidate
            if (partial.userName == undefined || _.isEmpty(partial.userName))
                throw new Error("You must provide a valid username");
            if (partial.password == undefined || _.isEmpty(partial.password))
                throw new Error("You must provide a valid password");
            if (partial.tenantName == undefined || _.isEmpty(partial.tenantName))
                throw new Error("You must provide a tenant name");
            let candidate = {
                newUser: true,
                userName: partial.userName,
                password: partial.password,
                tenantName: partial.tenantName
            };
            if (partial.firstName != undefined || !_.isEmpty(partial.firstName))
                candidate.firstName = partial.firstName;
            if (partial.lastName != undefined || !_.isEmpty(partial.lastName))
                candidate.lastName = partial.lastName;
            return candidate;
        });
    }
    execute(candidate) {
        var _a, _b, _c;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let result = yield this.authClient.Auth.TenantRegistration(candidate);
                if (result.error) {
                    if (_.isEmpty(result.error)) {
                        throw new Error((_a = result.message) !== null && _a !== void 0 ? _a : "no details provided.");
                    }
                    else {
                        throw result.error;
                    }
                }
                else if (result.output == undefined || result.output.Users == undefined || result.output.Users.length == 0) {
                    throw new Error("Registration failed without explicit error: ".concat((_b = result.message) !== null && _b !== void 0 ? _b : "no details provided."));
                }
                else if (result.success) {
                    const newTenant = result.output;
                    const newUser = result.output.Users[0];
                    let token = this.authClient.authToken; // <-- the gets overwritten with the return token.  Assertion ok here bc successful
                    let exp = this.authClient.extractTokenExpiration(token);
                    let roles = (_c = newUser.roles) === null || _c === void 0 ? void 0 : _c.map(r => r.name);
                    // TODO: log the current user in.
                    let userContextRepo = new user_context_loader_1.UserContextManager(this.cliEnviro, this.authClient, this.logger);
                    let newContext = yield userContextRepo.saveToUserContext(undefined, newUser.login, token, newUser.tenantCode, exp, roles);
                    this._ui.userMessage(this._styler.colorGood("Successfully registered!").concat(" user: ", newUser.login, " is the administrator for ", newTenant.name, " [", newTenant.code, "]"));
                }
            }
            catch (err) {
                this.handleError(err);
            }
        });
    }
}
exports.default = AuthRegister;
AuthRegister.description = 'Create your own user account.';
AuthRegister.examples = [
    '<%= config.bin %> <%= command.id %>',
];
AuthRegister.flags = {
    email: core_1.Flags.string({ char: 'u', description: "Must be a valid email. This will be your login/username on Codiac." }),
    password: core_1.Flags.string({ char: 'p', exclusive: ["passwordIn"], description: "password on Codiac in clear text.  NOT RECOMMENDED: use the `passwordIn` argument instead to transmit your password via stdin." }),
    passwordIn: core_1.Flags.boolean({ char: 'i', exclusive: ["password"], description: "Reads the password directly from the standard input stream.  Enables users to avoid explicitly rendering it in a command string. eg:  `cat mypass.txt | cod register -u joecool --passwordIn`.  Invokes `--silent` mode, so interaction will be disabled." }),
    company: core_1.Flags.string({ char: 'c', description: "Human readable friendly title for the organization (eg: 'ACME Anvils, Inc.').  NOT used for system identification.  NOTE: Users can belong to more than one organization; this one shall simply be the first for this user." }),
    companyCode: core_1.Flags.string({ description: "(optional) Unique identifier for the organization within Codiac (eg: 'acme').  This value IS used for system identification, and must be unique across all of Codiac.  This command will fail if this given company code is already taken (Must be 3 to 9 alphanumeric characters, no spaces or special characters)." }),
    firstName: core_1.Flags.string({ char: 'f', description: "(optional; you can edit this later)" }),
    lastName: core_1.Flags.string({ char: 'l', description: "(optional; you can edit this later)" }),
    // 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." })
};
AuthRegister.args = {};
//# sourceMappingURL=register.js.map