"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const helpers_1 = require("../../common/helpers");
class CreatePluginCommand {
    constructor($options, $errors, $terminalSpinnerService, $logger, $pacoteService, $fs, $childProcess, $prompter, $packageManager) {
        this.$options = $options;
        this.$errors = $errors;
        this.$terminalSpinnerService = $terminalSpinnerService;
        this.$logger = $logger;
        this.$pacoteService = $pacoteService;
        this.$fs = $fs;
        this.$childProcess = $childProcess;
        this.$prompter = $prompter;
        this.$packageManager = $packageManager;
        this.allowedParameters = [];
        this.userMessage = "What is your GitHub username?\n(will be used to update the Github URLs in the plugin's package.json)";
        this.nameMessage = "What will be the name of your plugin?\n(use lowercase characters and dashes only)";
    }
    execute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            const pluginRepoName = args[0];
            const pathToProject = this.$options.path;
            const selectedTemplate = this.$options.template;
            const selectedPath = path.resolve(pathToProject || ".");
            const projectDir = path.join(selectedPath, pluginRepoName);
            yield this.downloadPackage(selectedTemplate, projectDir);
            yield this.setupSeed(projectDir, pluginRepoName);
            this.$logger.printMarkdown("Solution for `%s` was successfully created.", pluginRepoName);
        });
    }
    canExecute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!args[0]) {
                this.$errors.fail("You must specify the plugin repository name.");
            }
            return true;
        });
    }
    setupSeed(projectDir, pluginRepoName) {
        return __awaiter(this, void 0, void 0, function* () {
            this.$logger.printMarkdown("Executing initial plugin configuration script...");
            const config = this.$options;
            const spinner = this.$terminalSpinnerService.createSpinner();
            const cwd = path.join(projectDir, "src");
            try {
                spinner.start();
                const npmOptions = { silent: true };
                yield this.$packageManager.install(cwd, cwd, npmOptions);
            }
            finally {
                spinner.stop();
            }
            const gitHubUsername = yield this.getGitHubUsername(config.username);
            const pluginNameSource = yield this.getPluginNameSource(config.pluginName, pluginRepoName);
            if (!helpers_1.isInteractive() && (!config.username || !config.pluginName)) {
                this.$logger.printMarkdown("Using default values for Github user and/or plugin name since your shell is not interactive.");
            }
            const pathToPostCloneScript = path.join("scripts", "postclone");
            const params = [pathToPostCloneScript, `gitHubUsername=${gitHubUsername}`, `pluginName=${pluginNameSource}`, "initGit=y"];
            const outputScript = (yield this.$childProcess.spawnFromEvent(process.execPath, params, "close", { cwd, timeout: 10000 }));
            if (outputScript && outputScript.stdout) {
                this.$logger.printMarkdown(outputScript.stdout);
            }
        });
    }
    downloadPackage(selectedTemplate, projectDir) {
        return __awaiter(this, void 0, void 0, function* () {
            this.$fs.createDirectory(projectDir);
            if (this.$fs.exists(projectDir) && !this.$fs.isEmptyDir(projectDir)) {
                this.$errors.fail("Path already exists and is not empty %s", projectDir);
            }
            if (selectedTemplate) {
                this.$logger.printMarkdown("Make sure your custom template is compatible with the Plugin Seed at https://github.com/NativeScript/nativescript-plugin-seed/");
            }
            else {
                this.$logger.printMarkdown("Downloading the latest version of NativeScript Plugin Seed...");
            }
            const spinner = this.$terminalSpinnerService.createSpinner();
            const packageToInstall = selectedTemplate || "https://github.com/NativeScript/nativescript-plugin-seed/archive/master.tar.gz";
            try {
                spinner.start();
                yield this.$pacoteService.extractPackage(packageToInstall, projectDir);
            }
            catch (err) {
                this.$fs.deleteDirectory(projectDir);
                throw err;
            }
            finally {
                spinner.stop();
            }
        });
    }
    getGitHubUsername(gitHubUsername) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!gitHubUsername) {
                gitHubUsername = "NativeScriptDeveloper";
                if (helpers_1.isInteractive()) {
                    gitHubUsername = yield this.$prompter.getString(this.userMessage, { allowEmpty: false, defaultAction: () => { return gitHubUsername; } });
                }
            }
            return gitHubUsername;
        });
    }
    getPluginNameSource(pluginNameSource, pluginRepoName) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!pluginNameSource) {
                const prefix = 'nativescript-';
                pluginNameSource = pluginRepoName.toLowerCase().startsWith(prefix) ? pluginRepoName.slice(prefix.length, pluginRepoName.length) : pluginRepoName;
                if (helpers_1.isInteractive()) {
                    pluginNameSource = yield this.$prompter.getString(this.nameMessage, { allowEmpty: false, defaultAction: () => { return pluginNameSource; } });
                }
            }
            return pluginNameSource;
        });
    }
}
exports.CreatePluginCommand = CreatePluginCommand;
$injector.registerCommand(["plugin|create"], CreatePluginCommand);
