"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const contracts_1 = require("../../../apis/codiac-api/contracts");
const command_base_exec_1 = require("../../../command-base-exec");
const config_ui_utils_1 = require("../../../uilogic/config-ui-utils");
const contracts_2 = require("../../../apis/codiac-relay/contracts");
;
class ClusterScalingUpdate 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(ClusterScalingUpdate);
            let partial = {};
            if (flags.enterprise)
                partial.enterprise = flags.enterprise;
            if (flags.cluster)
                partial.clusterName = flags.cluster;
            if (flags['node-group'])
                partial.nodeGroup = flags['node-group'];
            if (flags.min)
                partial.min = flags.min;
            if (flags.max)
                partial.max = flags.max;
            if (flags.desired)
                partial.desired = flags.desired;
            // ---------------------------------------------------------------
            // 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) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            // Find the requested cluster, default to the one and only, or throw a validation error 
            let cluster;
            if (partial.clusterName) {
                cluster = rootMap.clusters.find(c => c.name === partial.clusterName);
                if (!cluster) {
                    throw new Error("No cluster found with the given name.");
                }
            }
            else if (rootMap.clusters.length == 1) {
                cluster = rootMap.clusters[0];
                partial.clusterName = cluster.name;
            }
            if (!cluster) {
                throw new Error("No cluster provided; use the --cluster flag to specify an existing cluster name.");
            }
            else {
                // We've already found the cluster in the rootMap, so this query should always return our record.
                let clusterDef = (yield this._codiacApi.ClusterDef.readMany({ name: { $eq: cluster.name } }, { throwNotFound: true }))[0];
                // Find the requested nodegroup, default to the one and only, or throw a validation error 
                let nodeGroup;
                if (partial.nodeGroup) {
                    if (partial.nodeGroup === "original") {
                        nodeGroup = this.extractOriginalNodeGroup(clusterDef);
                    }
                    else if (clusterDef.nodePools && clusterDef.nodePools.length > 0) {
                        nodeGroup = clusterDef.nodePools.find(x => x.name === partial.nodeGroup);
                    }
                    if (nodeGroup == undefined) {
                        throw new Error("No node group found with the given name.");
                    }
                }
                else {
                    if (clusterDef.nodePools && clusterDef.nodePools.length > 0) {
                        throw new Error("No node group provided; use the --node-group flag to specify and existing node group name.");
                    }
                    else {
                        nodeGroup = this.extractOriginalNodeGroup(clusterDef);
                    }
                }
                // merge in existing values
                partial.nodeType = nodeGroup.nodeSpec;
                if (partial.min == undefined)
                    partial.min = nodeGroup.nodesMin;
                if (partial.max == undefined)
                    partial.max = nodeGroup.nodesMax;
                if (partial.desired == undefined)
                    partial.desired = nodeGroup.startingNodeCount;
            }
            return partial;
        });
    }
    buildCandidate_interactively(partial, rootMap, takeDefaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return this.buildCandidate_silently(partial, rootMap);
            // TODO: Add interactivity;
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("-e", candidate.enterprise);
        cmd.push("-c", candidate.clusterName);
        cmd.push("-n", candidate.nodeGroup);
        if (candidate.min)
            cmd.push("--min", candidate.min.toString());
        if (candidate.max)
            cmd.push("--max", candidate.max.toString());
        if (candidate.desired)
            cmd.push("--desired", candidate.desired.toString());
        return cmd;
    }
    executeTask(candidate) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            // let watcher = new LrpWatcher(this.relayWebSocket, this.logger);
            // let result = await watcher.triggerAndWatch("clusterCreate", "Creating cluster", (socketId: string) => this.genRelayClient.Call.clusterCreateAsync({
            //   spec: {
            //     name: "mcftest-to-DELETE",
            //     provider: CloudProviderEnum.aws,
            //     nodeSpec: candidate.nodeType ?? "t3.medium",
            //     locationName: "us-east-1",
            //     startingNodeCount: candidate.desired ?? 2,
            //     nodesMin: candidate.min ?? 1,
            //     nodesMax: candidate.max ?? 2,
            //     providerSubscription: "123test456",
            //     providerGroup: "n/a",
            //     created: new Date(Date.now()),
            //     createdBy: this._userCntx.userName,
            //     modified: new Date(Date.now()),
            //     modifiedBy: this._userCntx.userName,
            //     identitySpec: {}
            //   },
            //   socketId: socketId
            // }));
            // 
            // this.logger.debug("Recieved result", result);
            let result = yield this.watcher.triggerAndWatch((socketId) => {
                var _a, _b, _c, _d;
                return this.genRelayClient.Call.clusterCreateAsync({
                    spec: {
                        name: "mcftest-to-DELETE",
                        provider: contracts_2.CloudProviderEnum.aws,
                        nodeSpec: (_a = candidate.nodeType) !== null && _a !== void 0 ? _a : "t3.medium",
                        locationName: "us-west-1",
                        startingNodeCount: (_b = candidate.desired) !== null && _b !== void 0 ? _b : 2,
                        nodesMin: (_c = candidate.min) !== null && _c !== void 0 ? _c : 1,
                        nodesMax: (_d = candidate.max) !== null && _d !== void 0 ? _d : 2,
                        providerSubscription: "570376874173",
                        providerGroup: "n/a",
                        created: new Date(Date.now()),
                        createdBy: this._userCntx.userName,
                        modified: new Date(Date.now()),
                        modifiedBy: this._userCntx.userName,
                        identitySpec: { type: contracts_1.SecurityAccountTypeEnum.servicePrincipal, name: "" } // <-- this needs to be nullable!!
                    },
                    socketId: socketId
                });
            });
            if (result.error)
                throw result.error;
        });
    }
    unblockAndSleep(durationInSecs) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return new Promise(resolve => {
                setTimeout(() => resolve(), durationInSecs * 1000);
            });
        });
    }
    // ===============================================================================
    /** Converts the node pool definition that's part of the now legacy ClusterDef contract into a NodePoolDef object. */
    extractOriginalNodeGroup(clusterDef) {
        return {
            name: "original",
            clusterName: clusterDef.name,
            nodeSpec: clusterDef.nodeSpec,
            isWindows: false,
            nodesMin: clusterDef.nodesMin,
            nodesMax: clusterDef.nodesMax,
            startingNodeCount: clusterDef.startingNodeCount,
            created: clusterDef.created,
            createdBy: clusterDef.createdBy,
            modified: clusterDef.modified,
            modifiedBy: clusterDef.modifiedBy
        };
    }
}
exports.default = ClusterScalingUpdate;
ClusterScalingUpdate.hidden = true; // Keep this out of the help for now
ClusterScalingUpdate.description = 'Configures scaling rules for cluster node groups';
// static examples = [
//   '<%= config.bin %> <%= Command.id %>',
// ]
ClusterScalingUpdate.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    enterprise: core_1.Flags.string({ char: 'e', description: '(optional if there is only one) The enterprise to which the cluster belongs' }),
    cluster: core_1.Flags.string({ char: 'c', description: '(optional if there is only one) The cluster being scaled' }),
    "node-group": core_1.Flags.string({ char: 'n', description: '(optional if there is only one) Name of the node group to which the scaling rules apply.' }),
    min: core_1.Flags.integer({ required: false, description: 'Minimum number of nodes to allow (integer >= 0)' }),
    max: core_1.Flags.integer({ required: false, description: 'Maximum number of nodes to allow (integer >= 0)' }),
    desired: core_1.Flags.integer({ required: false, description: 'Number of nodes to start with and maintain (integer >= 0)' }),
    // 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." })
};
ClusterScalingUpdate.args = {
    file: core_1.Args.string({ description: 'file to read' }),
};
//# sourceMappingURL=update.js.map