"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CreateProjectCommand = void 0;
const constants = require("../constants");
const path = require("path");
const helpers_1 = require("../common/helpers");
const yok_1 = require("../common/yok");
const color_1 = require("../color");
class CreateProjectCommand {
    constructor($projectService, $logger, $errors, $options, $prompter, $stringParameter) {
        this.$projectService = $projectService;
        this.$logger = $logger;
        this.$errors = $errors;
        this.$options = $options;
        this.$prompter = $prompter;
        this.$stringParameter = $stringParameter;
        this.enableHooks = false;
        this.allowedParameters = [this.$stringParameter];
        this.isInteractionIntroShown = false;
    }
    execute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            const interactiveAdverbs = ["First", "Next", "Finally"];
            const getNextInteractiveAdverb = () => {
                return interactiveAdverbs.shift() || "Next";
            };
            if ((this.$options.tsc ||
                this.$options.ng ||
                this.$options.vue ||
                this.$options.react ||
                this.$options.svelte ||
                this.$options.js) &&
                this.$options.template) {
                this.$errors.failWithHelp("You cannot use a flavor option like --ng, --vue, --react, --svelte, --tsc and --js together with --template.");
            }
            let projectName = args[0];
            let selectedTemplate;
            if (this.$options["vision-ng"] ||
                (this.$options.vision && this.$options.ng)) {
                selectedTemplate = constants.RESERVED_TEMPLATE_NAMES["vision-ng"];
            }
            else if (this.$options["vision-react"] ||
                (this.$options.vision && this.$options.react)) {
                selectedTemplate = constants.RESERVED_TEMPLATE_NAMES["vision-react"];
            }
            else if (this.$options["vision-solid"]) {
                // note: we don't have solid templates or --solid
                selectedTemplate = constants.RESERVED_TEMPLATE_NAMES["vision-solid"];
            }
            else if (this.$options["vision-svelte"] ||
                (this.$options.vision && this.$options.svelte)) {
                selectedTemplate = constants.RESERVED_TEMPLATE_NAMES["vision-svelte"];
            }
            else if (this.$options["vision-vue"] ||
                (this.$options.vision && (this.$options.vue || this.$options.vuejs))) {
                selectedTemplate = constants.RESERVED_TEMPLATE_NAMES["vision-vue"];
            }
            else if ((this.$options.vue || this.$options.vuejs) &&
                this.$options.tsc) {
                selectedTemplate = "@nativescript/template-blank-vue-ts";
            }
            else if (this.$options.vision) {
                selectedTemplate = constants.RESERVED_TEMPLATE_NAMES["vision"];
            }
            else if (this.$options.js) {
                selectedTemplate = constants.JAVASCRIPT_NAME;
            }
            else if (this.$options.tsc) {
                selectedTemplate = constants.TYPESCRIPT_NAME;
            }
            else if (this.$options.ng) {
                selectedTemplate = constants.ANGULAR_NAME;
            }
            else if (this.$options.vue || this.$options.vuejs) {
                selectedTemplate = constants.VUE_NAME;
            }
            else if (this.$options.react) {
                selectedTemplate = constants.REACT_NAME;
            }
            else if (this.$options.svelte) {
                selectedTemplate = constants.SVELTE_NAME;
            }
            else {
                selectedTemplate = this.$options.template;
            }
            if (!projectName && (0, helpers_1.isInteractive)()) {
                this.printInteractiveCreationIntroIfNeeded();
                projectName = yield this.$prompter.getString(`${getNextInteractiveAdverb()}, what will be the name of your app?`, { allowEmpty: false });
                this.$logger.info();
            }
            projectName = yield this.$projectService.validateProjectName({
                projectName: projectName,
                force: this.$options.force,
                pathToProject: this.$options.path,
            });
            if (!selectedTemplate && (0, helpers_1.isInteractive)()) {
                this.printInteractiveCreationIntroIfNeeded();
                selectedTemplate = yield this.interactiveFlavorAndTemplateSelection(getNextInteractiveAdverb(), getNextInteractiveAdverb());
            }
            this.createdProjectData = yield this.$projectService.createProject({
                projectName: projectName,
                template: selectedTemplate,
                appId: this.$options.appid,
                pathToProject: this.$options.path,
                // its already validated above
                force: true,
                ignoreScripts: this.$options.ignoreScripts,
            });
        });
    }
    interactiveFlavorAndTemplateSelection(flavorAdverb, templateAdverb) {
        return __awaiter(this, void 0, void 0, function* () {
            const selectedFlavor = yield this.interactiveFlavorSelection(flavorAdverb);
            const selectedTemplate = yield this.interactiveTemplateSelection(selectedFlavor, templateAdverb);
            return selectedTemplate;
        });
    }
    interactiveFlavorSelection(adverb) {
        return __awaiter(this, void 0, void 0, function* () {
            const flavorSelection = yield this.$prompter.promptForDetailedChoice(`${adverb}, which style of NativeScript project would you like to use:`, [
                {
                    key: constants.NgFlavorName,
                    description: "Learn more at https://nativescript.org/angular",
                },
                {
                    key: constants.ReactFlavorName,
                    description: "Learn more at https://github.com/shirakaba/react-nativescript",
                },
                {
                    key: constants.VueFlavorName,
                    description: "Learn more at https://nativescript.org/vue",
                },
                {
                    key: constants.SvelteFlavorName,
                    description: "Learn more at https://svelte-native.technology",
                },
                {
                    key: constants.TsFlavorName,
                    description: "Learn more at https://nativescript.org/typescript",
                },
                {
                    key: constants.JsFlavorName,
                    description: "Use NativeScript without any framework",
                },
            ]);
            return flavorSelection;
        });
    }
    printInteractiveCreationIntroIfNeeded() {
        if (!this.isInteractionIntroShown) {
            this.isInteractionIntroShown = true;
            this.$logger.info();
            this.$logger.printMarkdown(`# Let’s create a NativeScript app!`);
            this.$logger.printMarkdown(`
Answer the following questions to help us build the right app for you. (Note: you
can skip this prompt next time using the --template option, or the --ng, --react, --vue, --svelte, --ts, or --js flags.)
`);
        }
    }
    interactiveTemplateSelection(flavorSelection, adverb) {
        return __awaiter(this, void 0, void 0, function* () {
            const selectedFlavorTemplates = [];
            let selectedTemplate;
            switch (flavorSelection) {
                case constants.NgFlavorName: {
                    selectedFlavorTemplates.push(...this.getNgTemplates());
                    break;
                }
                case constants.ReactFlavorName: {
                    selectedFlavorTemplates.push(...this.getReactTemplates());
                    break;
                }
                case constants.VueFlavorName: {
                    selectedFlavorTemplates.push(...this.getVueTemplates());
                    break;
                }
                case constants.SvelteFlavorName: {
                    selectedFlavorTemplates.push(...this.getSvelteTemplates());
                    break;
                }
                case constants.TsFlavorName: {
                    selectedFlavorTemplates.push(...this.getTsTemplates());
                    break;
                }
                case constants.JsFlavorName: {
                    selectedFlavorTemplates.push(...this.getJsTemplates());
                    break;
                }
            }
            if (selectedFlavorTemplates.length > 1) {
                this.$logger.info();
                const templateChoices = selectedFlavorTemplates.map((template) => {
                    return { key: template.key, description: template.description };
                });
                const selectedTemplateKey = yield this.$prompter.promptForDetailedChoice(`${adverb}, which template would you like to start from:`, templateChoices);
                selectedTemplate = selectedFlavorTemplates.find((t) => t.key === selectedTemplateKey).value;
            }
            else {
                selectedTemplate = selectedFlavorTemplates[0].value;
            }
            return selectedTemplate;
        });
    }
    getJsTemplates() {
        const templates = [
            {
                key: CreateProjectCommand.HelloWorldTemplateKey,
                value: constants.RESERVED_TEMPLATE_NAMES.javascript,
                description: CreateProjectCommand.HelloWorldTemplateDescription,
            },
            {
                key: CreateProjectCommand.DrawerTemplateKey,
                value: "@nativescript/template-drawer-navigation",
                description: CreateProjectCommand.DrawerTemplateDescription,
            },
            {
                key: CreateProjectCommand.TabsTemplateKey,
                value: "@nativescript/template-tab-navigation",
                description: CreateProjectCommand.TabsTemplateDescription,
            },
        ];
        return templates;
    }
    getTsTemplates() {
        const templates = [
            {
                key: CreateProjectCommand.HelloWorldTemplateKey,
                value: constants.RESERVED_TEMPLATE_NAMES.typescript,
                description: CreateProjectCommand.HelloWorldTemplateDescription,
            },
            {
                key: CreateProjectCommand.DrawerTemplateKey,
                value: "@nativescript/template-drawer-navigation-ts",
                description: CreateProjectCommand.DrawerTemplateDescription,
            },
            {
                key: CreateProjectCommand.TabsTemplateKey,
                value: "@nativescript/template-tab-navigation-ts",
                description: CreateProjectCommand.TabsTemplateDescription,
            },
            {
                key: CreateProjectCommand.BlankVisionTemplateKey,
                value: "@nativescript/template-hello-world-ts-vision",
                description: CreateProjectCommand.BlankVisionTemplateDescription,
            },
        ];
        return templates;
    }
    getNgTemplates() {
        const templates = [
            {
                key: CreateProjectCommand.HelloWorldTemplateKey,
                value: constants.RESERVED_TEMPLATE_NAMES.angular,
                description: CreateProjectCommand.HelloWorldTemplateDescription,
            },
            {
                key: CreateProjectCommand.DrawerTemplateKey,
                value: "@nativescript/template-drawer-navigation-ng",
                description: CreateProjectCommand.DrawerTemplateDescription,
            },
            {
                key: CreateProjectCommand.TabsTemplateKey,
                value: "@nativescript/template-tab-navigation-ng",
                description: CreateProjectCommand.TabsTemplateDescription,
            },
            {
                key: CreateProjectCommand.BlankVisionTemplateKey,
                value: "@nativescript/template-hello-world-ng-vision",
                description: CreateProjectCommand.BlankVisionTemplateDescription,
            },
        ];
        return templates;
    }
    getReactTemplates() {
        const templates = [
            {
                key: CreateProjectCommand.HelloWorldTemplateKey,
                value: constants.RESERVED_TEMPLATE_NAMES.react,
                description: CreateProjectCommand.HelloWorldTemplateDescription,
            },
            {
                key: CreateProjectCommand.BlankVisionTemplateKey,
                value: "@nativescript/template-blank-react-vision",
                description: CreateProjectCommand.BlankVisionTemplateDescription,
            },
        ];
        return templates;
    }
    getSvelteTemplates() {
        const templates = [
            {
                key: CreateProjectCommand.HelloWorldTemplateKey,
                value: constants.RESERVED_TEMPLATE_NAMES.svelte,
                description: CreateProjectCommand.HelloWorldTemplateDescription,
            },
            {
                key: CreateProjectCommand.BlankVisionTemplateKey,
                value: "@nativescript/template-blank-svelte-vision",
                description: CreateProjectCommand.BlankVisionTemplateDescription,
            },
        ];
        return templates;
    }
    getVueTemplates() {
        const templates = [
            {
                key: CreateProjectCommand.BlankTemplateKey,
                value: "@nativescript/template-blank-vue",
                description: CreateProjectCommand.BlankTemplateDescription,
            },
            {
                key: CreateProjectCommand.BlankTsTemplateKey,
                value: "@nativescript/template-blank-vue-ts",
                description: CreateProjectCommand.BlankTsTemplateDescription,
            },
            {
                key: CreateProjectCommand.DrawerTemplateKey,
                value: "@nativescript/template-drawer-navigation-vue",
                description: CreateProjectCommand.DrawerTemplateDescription,
            },
            {
                key: CreateProjectCommand.TabsTemplateKey,
                value: "@nativescript/template-tab-navigation-vue",
                description: CreateProjectCommand.TabsTemplateDescription,
            },
            {
                key: CreateProjectCommand.BlankVisionTemplateKey,
                value: "@nativescript/template-blank-vue-vision",
                description: CreateProjectCommand.BlankVisionTemplateDescription,
            },
        ];
        return templates;
    }
    postCommandAction(args) {
        return __awaiter(this, void 0, void 0, function* () {
            const { projectDir, projectName } = this.createdProjectData;
            const relativePath = path.relative(process.cwd(), projectDir);
            const greyDollarSign = color_1.color.grey("$");
            this.$logger.clearScreen();
            let runDebugNotes = [];
            if (this.$options.vision ||
                this.$options["vision-ng"] ||
                this.$options["vision-react"] ||
                this.$options["vision-solid"] ||
                this.$options["vision-svelte"] ||
                this.$options["vision-vue"]) {
                runDebugNotes = [
                    `Run the project on Vision Pro with:`,
                    "",
                    `  ${greyDollarSign} ${color_1.color.green("ns run visionos --no-hmr")}`,
                ];
            }
            else {
                runDebugNotes = [
                    `Run the project on multiple devices:`,
                    "",
                    `  ${greyDollarSign} ${color_1.color.green("ns run ios")}`,
                    `  ${greyDollarSign} ${color_1.color.green("ns run android")}`,
                    "",
                    "Debug the project with Chrome DevTools:",
                    "",
                    `  ${greyDollarSign} ${color_1.color.green("ns debug ios")}`,
                    `  ${greyDollarSign} ${color_1.color.green("ns debug android")}`,
                ];
            }
            this.$logger.info([
                [
                    color_1.color.green(`Project`),
                    color_1.color.cyan(projectName),
                    color_1.color.green(`was successfully created.`),
                ].join(" "),
                "",
                `Now you can navigate to your project with ${color_1.color.cyan(`cd ${relativePath}`)} and then:`,
                "",
                ...runDebugNotes,
                ``,
                `For more options consult the docs or run ${color_1.color.green("ns --help")}`,
                "",
            ].join("\n"));
            // todo: add back ns preview
            // this.$logger.printMarkdown(
            // 	`After that you can preview it on device by executing \`$ ns preview\``
            // );
        });
    }
}
CreateProjectCommand.BlankTemplateKey = "Blank";
CreateProjectCommand.BlankTemplateDescription = "A blank app";
CreateProjectCommand.BlankTsTemplateKey = "Blank Typescript";
CreateProjectCommand.BlankTsTemplateDescription = "A blank typescript app";
CreateProjectCommand.BlankVisionTemplateKey = "visionOS";
CreateProjectCommand.BlankVisionTemplateDescription = "A visionOS app";
CreateProjectCommand.HelloWorldTemplateKey = "Hello World";
CreateProjectCommand.HelloWorldTemplateDescription = "A Hello World app";
CreateProjectCommand.DrawerTemplateKey = "SideDrawer";
CreateProjectCommand.DrawerTemplateDescription = "An app with pre-built pages that uses a drawer for navigation";
CreateProjectCommand.TabsTemplateKey = "Tabs";
CreateProjectCommand.TabsTemplateDescription = "An app with pre-built pages that uses tabs for navigation";
exports.CreateProjectCommand = CreateProjectCommand;
yok_1.injector.registerCommand("create", CreateProjectCommand);
//# sourceMappingURL=create-project.js.map