"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HostNameUiLogic = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const command_base_exec_1 = require("../../command-base-exec");
const config_ui_utils_1 = require("../../uilogic/config-ui-utils");
const contracts_1 = require("../../apis/codiac-relay/contracts");
const codiac_constants_1 = require("../../codiac-constants");
const type_safety_utils_1 = require("../../uilogic/type-safety-utils");
class HostNameUiLogic {
    static displayNameFor(shn, styler) {
        const strat = shn.strategy.replace(/_dot_/g, ".").replace(/_slash_/g, "/");
        return styler.bold(shn.domainName).concat(styler.dim(" as "), strat, styler.dim(" > " + shn.scope + ": "), shn.target, (shn.isPrivate) ? ` (${codiac_constants_1.CliConstants.UTF8_FISHEYE}Private)` : "", type_safety_utils_1.TypeSafetyUtils.toBoolean(shn.thisMachine) ? " " + codiac_constants_1.CliConstants.UTF8_HOUSE : "");
    }
}
exports.HostNameUiLogic = HostNameUiLogic;
class HostDelete extends command_base_exec_1.CommandBaseExec {
    captureArgs() {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { args, flags } = yield this.parse(HostDelete);
            let partial = {};
            if (flags.enterprise)
                partial.enterprise = flags.enterprise;
            if (flags.id) {
                partial.id = flags.id;
            }
            else {
                partial.descriptor = {};
                if (flags.domain)
                    partial.descriptor.domainName = flags.domain;
                if (flags.naming)
                    partial.descriptor.strategy = type_safety_utils_1.TypeSafetyUtils.toEnum(contracts_1.HostNameStrategyEnum, flags.naming); // <--- the flags def's options constraint guarantees valid entry here.
                if (flags["enterprise-scope"]) {
                    partial.descriptor.scope = contracts_1.ScopeLevel.enterprise;
                    partial.descriptor.target = partial.enterprise;
                }
                else if (flags.environment) {
                    partial.descriptor.scope = contracts_1.ScopeLevel.environment;
                    partial.descriptor.target = flags.environment;
                }
                else if (flags.cabinet) {
                    partial.descriptor.scope = contracts_1.ScopeLevel.cabinet;
                    partial.descriptor.target = flags.cabinet;
                }
            }
            // ---------------------------------------------------------------
            // 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, rootMap) {
        var _a, _b, _c, _d;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let candidate;
            if (partial.id != undefined) {
                candidate = { enterprise: partial.enterprise, id: partial.id };
            }
            else {
                // 1) Check for missing input
                if (((_a = partial.descriptor) === null || _a === void 0 ? void 0 : _a.domainName) == undefined)
                    throw new Error("Missing domain (please set the --domain flag).");
                if (((_b = partial.descriptor) === null || _b === void 0 ? void 0 : _b.strategy) == undefined)
                    throw new Error("Missing naming strategy (please set the --naming flag).");
                if (((_c = partial.descriptor) === null || _c === void 0 ? void 0 : _c.scope) == undefined)
                    throw new Error("Missing scope (You must set one of the flags --enterprise-scope, --environment, or --cabinet).");
                if (((_d = partial.descriptor) === null || _d === void 0 ? void 0 : _d.target) == undefined)
                    throw new Error("Missing target (You must set one of the flags --enterprise-scope, --environment, or --cabinet)."); // This cant happen, but its here for consistency.
                // 2) validate before we fetch (Check for existence)
                const ent = rootMap.enterprises.find(e => e.name == candidate.enterprise);
                if (!ent)
                    throw new Error("Invalid enterprise: not found.");
                switch (partial.descriptor.scope) {
                    case contracts_1.ScopeLevel.environment:
                        if (!ent.environments.find(e => { var _a; return e.name == ((_a = partial.descriptor) === null || _a === void 0 ? void 0 : _a.target); }))
                            throw new Error("Invalid environment: not found.");
                        break;
                    case contracts_1.ScopeLevel.cabinet:
                        let cab;
                        for (let env of ent.environments) {
                            cab = env.cabinets.find(c => { var _a; return c.name == ((_a = partial.descriptor) === null || _a === void 0 ? void 0 : _a.target); });
                            if (cab)
                                continue;
                        }
                        if (cab == undefined)
                            throw new Error("Invalid cabinet: not found.");
                        break;
                }
                // 3) Fetch the id
                let req = {
                    enterprise: partial.enterprise,
                    domainName: { $eq: partial.descriptor.domainName },
                    strategy: { $eq: partial.descriptor.strategy },
                    scope: { $eq: partial.descriptor.scope.toString() },
                    target: { $eq: partial.descriptor.target }
                };
                let list = yield this._codiacApi.ScopedHostNameConfig.readMany(req);
                if (list.length > 0) {
                    // candidate = { enterprise: partial.enterprise, id: list[0].id! }; // <-- cant be undefined for existing records.
                    candidate = {
                        enterprise: list[0].enterprise,
                        descriptor: {
                            domainName: list[0].domainName,
                            strategy: list[0].strategy,
                            scope: type_safety_utils_1.TypeSafetyUtils.toEnum(contracts_1.HostNameStrategyEnum, list[0].scope),
                            target: list[0].target,
                            thisMachine: list[0].thisMachine
                        },
                        id: list[0].id
                    };
                }
                else {
                    throw new Error("Domain mapping strategy not found (Please check the ingressMap with: cod host view).");
                }
            }
            return candidate;
        });
    }
    buildCandidate_interactively(partial, rootMap, takeDefaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let list = yield this._codiacApi.ScopedHostNameConfig.readMany({ all: true, enterprise: partial.enterprise });
            if (list.length == 0) {
                this._ui.userMessage("There are no host name mappings in the enterprise ".concat(partial.enterprise, ". No work to do."));
                this.exit(0);
            }
            let selected;
            let found = list.filter(shn => {
                var _a, _b, _c, _d;
                if (partial.id) {
                    return Boolean(shn.id == partial.id);
                }
                else {
                    let include = true;
                    if ((_a = partial.descriptor) === null || _a === void 0 ? void 0 : _a.domainName)
                        include = include && (shn.domainName == partial.descriptor.domainName);
                    if ((_b = partial.descriptor) === null || _b === void 0 ? void 0 : _b.strategy)
                        include = include && (shn.strategy == partial.descriptor.strategy);
                    if ((_c = partial.descriptor) === null || _c === void 0 ? void 0 : _c.scope)
                        include = include && (shn.scope == partial.descriptor.target);
                    if ((_d = partial.descriptor) === null || _d === void 0 ? void 0 : _d.target)
                        include = include && (shn.domainName == partial.descriptor.target);
                    return include;
                }
            });
            if (found.length == 1) {
                selected = found[0];
            }
            let keep = false;
            if (selected) {
                keep = yield this._ui.promptConfirm("confirmShn", "Delete: ".concat(HostNameUiLogic.displayNameFor(selected, this._styler)), false);
            }
            if (!keep && list.length == 1) {
                this._ui.userMessage("There are no other host name mappings.  No work was done.");
                this.exit(0);
                return undefined; // this line wont get hit - it's here for ts consistency 
            }
            if (!selected || !keep) {
                let choices = list.map(shn => ({ name: HostNameUiLogic.displayNameFor(shn, this._styler), value: shn.id }));
                let selectedId = yield this._ui.promptSelect("shn", "Delete: ", choices, false, false);
                selected = list.find(x => x.id == selectedId); // assertion ok - the choices came from this list
            }
            let candidate = {
                enterprise: selected.enterprise,
                id: selected.id
            };
            // Only populate the descriptor if the user enter them originally as command params. 
            // (For use in building the command string; this is how we determine 
            // if they came in with an id or with descriptor args).
            if (!partial.id) {
                const scope = type_safety_utils_1.TypeSafetyUtils.toEnum(contracts_1.ScopeLevel, selected.scope);
                if (scope == undefined)
                    throw new Error("Unrecognized Scope");
                candidate.descriptor = {
                    domainName: selected.domainName,
                    strategy: selected.strategy,
                    scope: scope,
                    target: selected.target,
                    thisMachine: selected.thisMachine
                };
            }
            return candidate;
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("--enterprise", candidate.enterprise);
        if (candidate.descriptor) {
            // DEVNOTE: Assertions ok here bc we already guaranteed that descriptor is all or nothing.
            cmd.push("--domain", candidate.descriptor.domainName);
            cmd.push("--naming", candidate.descriptor.strategy.toString());
            switch (candidate.descriptor.scope) {
                case contracts_1.ScopeLevel.enterprise:
                    cmd.push("--enterprise-scope");
                    break;
                case contracts_1.ScopeLevel.environment:
                    cmd.push("--environment", candidate.descriptor.target);
                    break;
                case contracts_1.ScopeLevel.cabinet:
                    cmd.push("--cabinet", candidate.descriptor.target);
                    break;
            }
        }
        else {
            if (candidate.id)
                cmd.push("--id", candidate.id); // this if stmt will always be true.
        }
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        var _a, _b, _c, _d;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            let idToDelete = candidate.id;
            this._ui.startSpinner("Removing domain mapping");
            const delRes = yield this.genRelayClient.Call.domainDelete({ id: idToDelete, thisMachine: (_a = candidate.descriptor) === null || _a === void 0 ? void 0 : _a.thisMachine });
            this._ui.stopSpinner(delRes.success ? "Completed" : "Failed");
            if (delRes.error)
                throw delRes.error;
            if (delRes.success != true || delRes.output == undefined) {
                this._ui.userMessage("Failed without error. ".concat((_b = delRes.message) !== null && _b !== void 0 ? _b : "(see logs for more info)").trim());
            }
            else {
                const obj = (_c = delRes.output) !== null && _c !== void 0 ? _c : candidate;
                this._ui.userMessage(this._styler.colorGood("Success!").concat(" ", (_d = delRes.message) !== null && _d !== void 0 ? _d : "Deleted domain [", obj.domainName, "] mapped as ", obj.strategy.toString(), " to ", obj.scope.toString(), ": ", obj.target).trim());
            }
        });
    }
}
exports.default = HostDelete;
HostDelete.description = 'Removes a host naming strategy mapping.  ie: UN-maps a domain strategy that was previously assigned to a given scope (eg: enterprise, environment, or cabinet.';
HostDelete.examples = [
    '<%= config.bin %> <%= command.id %>',
];
HostDelete.flags = {
    enterprise: core_1.Flags.string({ char: 'e', description: 'The name of the enterprise on which to apply this naming strategy. NOTE: You can leave this blank if there is only one.' }),
    domain: core_1.Flags.string({ char: "d", exclusive: ["id"], description: 'domain name to remove (without any wildcards), eg: `yoursite.com`' }),
    naming: core_1.Flags.string({ char: 'n', exclusive: ["id"], required: false, options: Object.values(contracts_1.HostNameStrategyEnum), description: "The host naming strategy to apply." }),
    "enterprise-scope": core_1.Flags.boolean({ char: 's', exclusive: ["id", "environment", "cabinet"], description: 'Applies the naming strategy at the enterprise level.' }),
    environment: core_1.Flags.string({ char: 'v', exclusive: ["id", "enterprise-scope", "cabinet"], description: 'The name of the environment on which to apply this naming strategy. Must be qualified by also setting enterprise.  NOTE: You can leave this blank if there is only one.' }),
    cabinet: core_1.Flags.string({ char: 'c', exclusive: ["id", "enterprise-scope", "environment"], description: 'The name of the cabinet on which to apply this naming strategy.  Must be qualified by also setting enterprise.  NOTE: You can leave this blank if there is only one. If cabinet names are not unique, use the --enterprise/-e argument to fully qualify the cabinet name.' }),
    id: core_1.Flags.string({ exclusive: ["enterprise", "domain", "naming", "enterprise-scope", "environment", "cabinet"], description: "The system id of the domain mapping itself. You can enter this parameter instead of the other domain mapping descriptors." }),
    // 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." })
};
HostDelete.args = {};
//# sourceMappingURL=delete.js.map