"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PROMPT_ME_DESIGNATOR = void 0;
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 prettify_1 = require("../../prettify");
/** The value provided as input that indicates
 * a user's desire to be prompted with a list from which choose the value(s),
 * instead of entering them manually or taking a default. */
exports.PROMPT_ME_DESIGNATOR = "?";
class KitCreate extends command_base_exec_1.CommandBaseExec {
    captureArgs() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(KitCreate);
            let partial = {};
            if (flags.enterprise)
                partial.enterprise = flags.enterprise;
            return [partial, false];
        });
    }
    buildCandidate_silently(partial, rootMap) {
        var _a;
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(KitCreate);
            if (!flags.asset)
                throw new Error("Asset name (--asset or -a) is required in silent mode.");
            const asset = yield this.fetchAsset(partial.enterprise, flags.asset);
            const kitRes = yield this.genRelayClient.Call.getGenerateKit({ assetName: asset.name, enterprise: asset.enterprise });
            if (!kitRes.success || !kitRes.output)
                throw (_a = kitRes.error) !== null && _a !== void 0 ? _a : new Error(`Failed to generate kit template for asset "${asset.name}".`);
            const kit = kitRes.output;
            if (flags.name)
                kit.name = flags.name;
            if (flags.scope)
                kit.library = flags.scope;
            return { enterprise: partial.enterprise, kit };
        });
    }
    buildCandidate_interactively(partial, rootMap, takeDefaults) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const { flags } = yield this.parse(KitCreate);
            const asset = yield this.promptForAsset(partial.enterprise, flags.asset);
            const kitRes = yield this.genRelayClient.Call.getGenerateKit({ assetName: asset.name, enterprise: asset.enterprise });
            if (!kitRes.success || !kitRes.output) {
                if (kitRes.error)
                    throw kitRes.error;
                return undefined;
            }
            let candidate = kitRes.output;
            // Multi-round edit loop
            let confirmed = false;
            while (!confirmed) {
                console.clear();
                this._ui.userMessage(this._styler.bold("New Kit:"));
                candidate.name = (yield this._ui.prompt("name", "Name: ", true, candidate.name));
                candidate.library = (yield this._ui.prompt("library", "Library: ", true, candidate.library));
                candidate.description = (yield this._ui.prompt("description", "Description: ", true, candidate.description));
                const accessChoices = [contracts_1.KitAccessibilityEnum.private, contracts_1.KitAccessibilityEnum.friends, contracts_1.KitAccessibilityEnum.public];
                candidate.accessibleBy = (yield this._ui.promptSelect("accessibleBy", "AccessibleBy: ", accessChoices, false));
                console.clear();
                this._ui.userMessage((0, prettify_1.prettify)(candidate));
                this._ui.userMessage(`You are about to create this kit. Continue?`);
                confirmed = yield this._ui.promptConfirm("confirmCreate", `(hit 'N' to edit your input)`, false);
            }
            return { enterprise: partial.enterprise, kit: candidate };
        });
    }
    buildCommandString(candidate, cmd) {
        cmd.push("-e", candidate.enterprise);
        cmd.push("-a", candidate.kit.name);
        cmd.push("--silent");
        return cmd;
    }
    executeTask(candidate) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const result = yield this._codiacApi.Kit.tryCreate(candidate.kit);
            if (result.error)
                throw result.error;
            const kitFqn = `${candidate.kit.library}/${candidate.kit.name}`;
            if (!result.success || !result.output)
                throw new Error(`Failed without error creating kit [${kitFqn}]: ${result.message}.`);
            this.logger.notice(`${this._styler.colorGood("SUCCESS!")} Created new kit ${this._styler.bold(this._styler.hilite(kitFqn))}.`, result.output);
            this._ui.userMessage(`${this._styler.colorGood("SUCCESS!")} Created new kit ${this._styler.bold(this._styler.hilite(kitFqn))}.`);
        });
    }
    fetchAsset(enterprise, assetName) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const ecrit = { code: enterprise };
            const readResult = yield this._codiacApi.Enterprise.tryReadMany(ecrit);
            if (!readResult.output || readResult.output.length === 0)
                throw new Error(`Could not find enterprise [${enterprise}].`);
            if (!readResult.output[0].assets || readResult.output[0].assets.length === 0)
                throw new Error(`The enterprise [${enterprise}] has no assets defined.`);
            let assets = readResult.output[0].assets;
            assets = assets.filter(a => a.name.startsWith(assetName));
            if (assets.length === 0)
                throw new Error(`No asset found with name starting with "${assetName}" in enterprise "${enterprise}".`);
            return assets[0];
        });
    }
    promptForAsset(enterprise, assetSearch) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const ecrit = { code: enterprise };
            const readResult = yield this._codiacApi.Enterprise.tryReadMany(ecrit);
            if (!readResult.output || readResult.output.length === 0)
                throw new Error(`Could not find enterprise [${enterprise}].`);
            if (!readResult.output[0].assets || readResult.output[0].assets.length === 0)
                throw new Error(`The enterprise [${enterprise}] has no assets defined.`);
            let assets = readResult.output[0].assets;
            if (assetSearch && assetSearch !== exports.PROMPT_ME_DESIGNATOR) {
                assets = assets.filter(a => a.name.startsWith(assetSearch));
            }
            const choices = assets.map(a => ({ name: a.name, value: a.name })).sort((a, b) => a.name.localeCompare(b.name));
            const selectedName = yield this._ui.promptSelectFuzzy('asset', 'Select an Asset:', () => tslib_1.__awaiter(this, void 0, void 0, function* () { return choices; }));
            const selected = assets.find(a => a.name === selectedName);
            if (!selected)
                throw new Error(`User failed to select a valid asset.`);
            return selected;
        });
    }
}
exports.default = KitCreate;
KitCreate.description = 'Creates a new kit from an existing asset.';
KitCreate.aliases = [];
KitCreate.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    asset: core_1.Flags.string({ char: 'a', required: false, description: "The enterprise asset from which to create the kit." }),
    enterprise: core_1.Flags.string({ char: 'e', required: false, description: 'The name of the enterprise containing the given asset (defaults to the current enterprise context).' }),
    name: core_1.Flags.string({ char: 'n', required: false, description: "Override for the name to give the new kit (optional; defaults to the asset name)." }),
    scope: core_1.Flags.string({ char: 's', required: false, description: "The globally unique directory name in which to register the kit, prefixed to the kit name for global uniqueness (optional; defaults to the public shared library)." }),
    silent: core_1.Flags.boolean({ exclusive: ["echo", "to-script"], description: 'Executes without any user interaction; fails on missing or invalid arguments.' }),
    echo: core_1.Flags.boolean({ exclusive: ["to-script", "silent"], description: 'Renders the equivalent non-interactive command for future use before executing.' }),
    "to-script": core_1.Flags.boolean({ exclusive: ["echo", "silent"], description: 'Renders the equivalent non-interactive command without executing it.' }),
};
KitCreate.args = {};
KitCreate.examples = [
    { description: "Create a kit interactively.", command: "<%= config.bin %> <%= command.id %>" },
    { description: "Create a kit from a specific asset.", command: "<%= config.bin %> <%= command.id %> -e myEnterprise -a myApi" },
    { description: "Non-interactive (scripted) invocation.", command: "<%= config.bin %> <%= command.id %> -e myEnterprise -a myApi --silent" },
    { description: "Renders the equivalent silent command without executing.", command: "<%= config.bin %> <%= command.id %> -e myEnterprise -a myApi --to-script" },
];
//# sourceMappingURL=create.js.map