"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PromptDefForString = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const contracts_1 = require("../../apis/codiac-relay/contracts");
const prettify_1 = require("../../prettify");
const command_base_exec_1 = require("../../command-base-exec");
const type_safety_utils_1 = require("../../uilogic/type-safety-utils");
const uilogic_1 = require("../../uilogic");
class PromptDefForString {
    constructor(promptText, promptId, isValid, getFromUser) {
        this.promptText = promptText;
        this.promptId = promptId;
        this.isValid = isValid;
        this.getFromUser = getFromUser;
    }
}
exports.PromptDefForString = PromptDefForString;
class FilestoreCapture extends command_base_exec_1.CommandBaseExec {
    constructor() {
        super(...arguments);
        this.localCache = {};
        //  COMMENTED OUT BC: not in use.
        // /** Factory method for building a FileStoreDef from a fileshare */
        // private buildFileStoreDef(provider: CloudProviderEnum, providerSubscriptionId: string, storageAccount: StorageAccount, resourceGroup: string, accountKey: string, fileShareName: string): FileStoreDef {
        //     let def: FileStoreDef = {
        //         id: undefined,
        //         name: fileShareName,
        //         provider: provider,
        //         providerSubscriptionId: providerSubscriptionId,
        //         resourceGroup: resourceGroup,
        //         storageAccount: storageAccount.name,
        //         shareName: fileShareName,
        //         type: FileStoreTypeEnum.AzureFileStorage,
        //         instance: {
        //             accessKey: accountKey,
        //             providerSubscriptionId: providerSubscriptionId,
        //             resourceGroup: resourceGroup,
        //             resourceId: storageAccount.id!
        //         },
        //         created: new Date(Date.now()),
        //         createdBy: this._userCntx.userName,
        //         modified: new Date(Date.now()),
        //         modifiedBy: this._userCntx.userName
        //     };
        //     return def;
        // }
    }
    bootstrap() {
        super.bootstrap();
        uilogic_1.FileStoreConfiguratorFactory.bootstrap(this.ioc);
    }
    get filestoreUiFactory() {
        if (this.__filestoreUiFactory == undefined) {
            this.__filestoreUiFactory = new uilogic_1.FileStoreConfiguratorFactory(this.ioc);
        }
        return this.__filestoreUiFactory;
    }
    get fileStoreCspMap() {
        if (this.__fileStoreCspMap == undefined) {
            this.__fileStoreCspMap = {
                [contracts_1.FileStoreTypeEnum.azureBlobStorage]: contracts_1.CloudProviderEnum.azure,
                [contracts_1.FileStoreTypeEnum.azureDisk]: contracts_1.CloudProviderEnum.azure,
                [contracts_1.FileStoreTypeEnum.azureFileStorage]: contracts_1.CloudProviderEnum.azure,
                [contracts_1.FileStoreTypeEnum.awsEfs]: contracts_1.CloudProviderEnum.aws,
                [contracts_1.FileStoreTypeEnum.awsEbs]: contracts_1.CloudProviderEnum.aws,
                [contracts_1.FileStoreTypeEnum.awsS3Bucket]: contracts_1.CloudProviderEnum.aws,
                [contracts_1.FileStoreTypeEnum.hostMachineFolder]: contracts_1.CloudProviderEnum.other
            };
        }
        return this.__fileStoreCspMap;
    }
    captureArgs() {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { args, flags } = yield this.parse(FilestoreCapture);
            let partial = {};
            partial.enterprise = flags.enterprise;
            partial.name = flags.name;
            if (flags.provider)
                partial.provider = type_safety_utils_1.TypeSafetyUtils.toEnum(contracts_1.CloudProviderEnum, flags.provider);
            partial.providerSubscriptionId = flags.providerSubscriptionId;
            partial.shareName = flags.shareName;
            if (partial.provider == contracts_1.CloudProviderEnum.azure) {
                partial.resourceGroup = flags.resourceGroup;
                partial.storageAccount = flags.storageAccount;
            }
            // ---------------------------------------------------------------
            // TODO: turn this into setInteractionMode() and move everything from here down into the base class
            // ---------------------------------------------------------------
            const interactionMode = this.getInteractionMode(flags.silent, flags.echo, flags['to-script']);
            const takeDefaults = (_a = flags['take-defaults']) !== null && _a !== void 0 ? _a : false;
            return [partial, interactionMode, takeDefaults];
        });
    }
    buildCandidate_silently(partial, rootMap) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (partial.enterprise == undefined || partial.enterprise.trim() == "")
                throw new Error("Must provide enterprise.");
            if (partial.name == undefined || partial.name.trim() == "")
                throw new Error("Must provide name.");
            if (partial.providerSubscriptionId == undefined || partial.providerSubscriptionId.trim() == "")
                throw new Error("Must provide providerSubscriptionId.");
            if (partial.provider == undefined || partial.provider.trim() == "") {
                if (partial.type !== undefined) {
                    partial.provider = this.fileStoreCspMap[partial.type];
                }
                else {
                    throw new Error("Must submit cloud provider.");
                }
            }
            if (rootMap.enterprises.find(e => e.name == partial.enterprise) == undefined)
                throw new Error("Enterprise not found."); // Enterprise contextualizer will already have done this for us, right?
            let filestoreUi = yield this.filestoreUiFactory.create(partial.provider);
            let fileStore = yield filestoreUi.captureFileStore(partial.providerSubscriptionId, partial, false);
            if (fileStore == undefined)
                throw new Error("Filestore not found.");
            if (partial.provider)
                fileStore.provider = partial.provider;
            const output = Object.assign(Object.assign({}, fileStore), { enterprise: partial.enterprise });
            return output;
        });
    }
    buildCandidate_interactively(partial, rootMap, takeDefaults) {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let fileStore;
                let confirmed = false;
                do {
                    // 1. Select a cloud resource provider
                    let choices = this.filestoreUiFactory.getAllProviders();
                    partial.provider = (yield this.cspContextualizer.promptForCloudProvider(choices, partial.provider));
                    // 2. Authenticate with the cloud resource provider
                    let cspUser = yield this.cspContextualizer.promptForCloudProviderCreds(this.ioc, partial.provider, undefined, undefined, undefined, partial.providerSubscriptionId);
                    partial.providerSubscriptionId = (_a = cspUser.subscriptionId) !== null && _a !== void 0 ? _a : yield this.promptForSubscription(cspUser.username, partial.providerSubscriptionId);
                    let filestoreUi = yield this.filestoreUiFactory.create(partial.provider);
                    fileStore = yield filestoreUi.captureFileStore(partial.providerSubscriptionId, partial, true);
                    // Confirm
                    if (fileStore) {
                        console.clear();
                        this._ui.userMessage((0, prettify_1.prettify)(fileStore));
                        confirmed = yield this._ui.promptConfirm("filestore", `You have selected [${fileStore.provider}/${fileStore.shareName}]. Is this correct?`, true);
                    }
                } while ((confirmed != true) && (fileStore == undefined));
                return Object.assign(Object.assign({}, fileStore), { enterprise: partial.enterprise, provider: partial.provider });
            }
            catch (err) {
                throw err;
            }
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("--silent");
        cmd.push("--enterprise", candidate.enterprise);
        cmd.push("--name", candidate.name);
        cmd.push("--provider", candidate.provider);
        cmd.push("--providerSubscriptionId", candidate.providerSubscriptionId);
        cmd.push("--shareName", candidate.shareName);
        if (candidate.provider == contracts_1.CloudProviderEnum.azure) {
            cmd.push("--resourceGroup", candidate.resourceGroup);
            cmd.push("--storageAccount", candidate.storageAccount);
        }
        return cmd;
    }
    executeTask(candidate) {
        var _a, _b;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let result = yield this._codiacApi.FileStoreDef.tryCreate(candidate);
                if (result.error)
                    throw result.error;
                if (!result.success || !result.output)
                    throw new Error(`Failed without error writing FileStoreDef record [${candidate.name}]: ${result.message}.`);
                this.logger.notice(`${this._styler.colorGood("SUCCESS!")} Created new fileStoreDef record ${this._styler.bold(this._styler.hilite(candidate.name))}.`, result.output);
                this._ui.userMessage(`${this._styler.colorGood("SUCCESS!")} Created new fileStoreDef record ${this._styler.bold(this._styler.hilite(candidate.name))}.`);
                return;
            }
            catch (err) {
                this.logger.error((_b = (_a = err.message) !== null && _a !== void 0 ? _a : err.stack) !== null && _b !== void 0 ? _b : err, candidate);
                throw err;
            }
        });
    }
    // -------------------------------------------------------------------------------------------------------------------------
    // SUPPORTING METHODS
    // -------------------------------------------------------------------------------------------------------------------------
    // COMMENTED OUT BC: Not in use.
    // /** Throws any encounted exceptions. */
    // private extractResourceGroup(storageAccountResourceId: string): string {
    //     // We have to parse the resourceGroup out of the id bc M$ doesnt return it anywhere else.  Yeah, dont you just love those guys :|
    //     let rg = new RegExp(/\/resourceGroups\/([^\/]+)\//).exec(storageAccountResourceId!)![1];
    //     return rg;
    // }
    /** Implements the confirm default or prompt for value pattern. */
    confirmOrPrompt(promptDef, defaultValue, defaultValueDisplay) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let output;
                let keepDefault = false;
                if (defaultValue && promptDef.isValid(defaultValue)) {
                    keepDefault = yield this._ui.promptConfirm(`keep${promptDef.promptId}`, `${promptDef.promptText}: ${defaultValueDisplay !== null && defaultValueDisplay !== void 0 ? defaultValueDisplay : defaultValue}`);
                }
                if (keepDefault === true && defaultValue !== undefined) {
                    output = defaultValue;
                }
                else {
                    output = yield promptDef.getFromUser(defaultValue);
                }
                return output;
            }
            catch (err) {
                throw err;
            }
        });
    }
    promptForSubscription(azUser, defaultValue) {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            try {
                let subxId;
                if (this.localCache.subscriptions === undefined) {
                    let subxResult = yield this.genRelayClient.Call.getAzureSubscriptions({ azUser: azUser });
                    if (subxResult.error)
                        throw subxResult.error;
                    this.localCache.subscriptions = (_a = subxResult.output) !== null && _a !== void 0 ? _a : [];
                }
                let subxs = this.localCache.subscriptions;
                let subx = (defaultValue !== undefined) ? subxs.find(s => s.id === defaultValue) : undefined;
                let defaultValueDisplay = (subx !== undefined) ? `${this._styler.hilite(subx.name)} (${subx.id})` : undefined;
                let promptDef = {
                    promptId: "subxId",
                    promptText: "Provider subscription",
                    isValid: (defaultVal) => Boolean(subx !== undefined),
                    getFromUser: (defaultVal) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                        let choices = (subxs).map(s => { return { name: `${s.name}  (as ${s.user.name})`, value: s.id }; });
                        subxId = (yield this._ui.promptSelect("providerSubscriptionId", "select the cloud provider subscription", choices));
                        return subxId;
                    })
                };
                subxId = yield this.confirmOrPrompt(promptDef, defaultValue, defaultValueDisplay);
                // let isValid = (sid: string) => Boolean(subx !== undefined);
                // let keepDefault = false;
                // if (defaultValue && isValid(defaultValue)) {
                //     keepDefault = await this._ui.promptConfirm("keepSubxId", `Provider subscription: ${this._styler.hilite(subx!.name)} (${subx!.id})`);
                // }
                // if (keepDefault === true && defaultValue !== undefined) {
                //     subxId = defaultValue;
                // } else {
                //     let choices = (subxs).map(s => { return { name: `${s.name}  (as ${s.user.name})`, value: s.id } });
                //     subxId = (await this._ui.promptSelect<string>("providerSubscriptionId", "select the cloud provider subscription", choices))!;
                // }
                return subxId;
            }
            catch (err) {
                throw err;
            }
        });
    }
}
exports.default = FilestoreCapture;
FilestoreCapture.description = 'Creates a reference point in the given enterprise for an existing filestore instance in a cloud provider subscription.';
FilestoreCapture.aliases = ['fileshare:capture'];
FilestoreCapture.dependsOn = ["enterprise", "name", "providerSubscriptionId", "storageAccount", "shareName"];
FilestoreCapture.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    enterprise: core_1.Flags.string({ char: 'e', required: false, description: 'The name of the enterprise in which to create this filestore. (defaults to the current enterprise context)' }),
    name: core_1.Flags.string({ char: 'n', required: false, description: "The name by which to identify this fileshare definition within the enterprise (Optional: defaults to the shareName)." }),
    provider: core_1.Flags.string({ required: false, options: [contracts_1.CloudProviderEnum.azure], description: 'The cloud provider under which the file storage account resides.' }),
    providerSubscriptionId: core_1.Flags.string({ required: false, description: 'The identifier of the cloud provider subscription under which the file storage account resides.' }),
    storageAccount: core_1.Flags.string({ required: false, description: 'The name within the cloud provider of the file storage account within which the share resides.' }),
    shareName: core_1.Flags.string({ required: false, description: 'The name of the fileshare to connect to within the file storage account.' }),
    resourceGroup: core_1.Flags.string({ required: false, description: 'The name of the Azure resource group under which the instance is to be created  (Azure-specific).' }),
    // resourceId: flags.string({ required: false, description: 'The unique identifier given by the cloud provider to the file storage account.'}),
    // accessKey: flags.string({ required: false, description: 'The key generated upon creation of the FileStore, to enable the consumer to attach to it.'}),
    silent: core_1.Flags.boolean({ dependsOn: FilestoreCapture.dependsOn, required: false, 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.' }),
    //Not sure what to do with this one yet
    "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)." })
};
//# sourceMappingURL=capture.js.map