"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 helpers = require("../common/helpers");
const path = require("path");
const semver = require("semver");
const os_1 = require("os");
const constants_1 = require("../constants");
class WorkflowService {
    constructor($bundleValidatorHelper, $fs, $logger, $packageManager, $projectDataService, $prompter, $options) {
        this.$bundleValidatorHelper = $bundleValidatorHelper;
        this.$fs = $fs;
        this.$logger = $logger;
        this.$packageManager = $packageManager;
        this.$projectDataService = $projectDataService;
        this.$prompter = $prompter;
        this.$options = $options;
        this.legacyWorkflowDeprecationMessage = `With the upcoming NativeScript 6.0 the Webpack workflow will become the only way of building apps.
More info about the reasons for this change and how to migrate your project can be found in the link below:
https://www.nativescript.org/blog/the-future-of-building-nativescript-apps`;
        this.webpackWorkflowConfirmMessage = `Do you want to switch your app to the Webpack workflow?`;
    }
    handleLegacyWorkflow(options) {
        return __awaiter(this, void 0, void 0, function* () {
            const { projectDir, settings, skipWarnings, force } = options;
            if (!settings.bundle || force) {
                const projectData = this.$projectDataService.getProjectData(projectDir);
                if (typeof (projectData.useLegacyWorkflow) !== "boolean" || force) {
                    const hasSwitched = yield this.handleWebpackWorkflowSwitch(projectData, skipWarnings, force);
                    if (hasSwitched) {
                        this.$options.bundle = "webpack";
                        this.$options.hmr = !settings.release;
                        if (typeof (settings.bundle) === "boolean") {
                            settings.bundle = true;
                        }
                        else {
                            settings.bundle = this.$options.bundle;
                        }
                        settings.useHotModuleReload = this.$options.hmr;
                    }
                }
                else if (!skipWarnings && projectData.useLegacyWorkflow === true) {
                    this.showLegacyWorkflowWarning();
                }
                else if (!skipWarnings && projectData.useLegacyWorkflow === false) {
                    this.showNoBundleWarning();
                }
            }
        });
    }
    handleWebpackWorkflowSwitch(projectData, skipWarnings, force) {
        return __awaiter(this, void 0, void 0, function* () {
            let hasSwitched = force;
            if (force || helpers.isInteractive()) {
                if (!force) {
                    this.$logger.info();
                    this.$logger.printMarkdown(`
__Improve your project by switching to the Webpack workflow.__

\`${this.legacyWorkflowDeprecationMessage}\``);
                    hasSwitched = yield this.$prompter.confirm(this.webpackWorkflowConfirmMessage, () => true);
                }
                if (hasSwitched) {
                    this.$projectDataService.setUseLegacyWorkflow(projectData.projectDir, false);
                    yield this.ensureWebpackPluginInstalled(projectData);
                }
                else {
                    this.$projectDataService.setUseLegacyWorkflow(projectData.projectDir, true);
                }
            }
            else if (!skipWarnings) {
                yield this.showLegacyWorkflowWarning();
            }
            return hasSwitched;
        });
    }
    showLegacyWorkflowWarning() {
        const legacyWorkflowWarning = `You are using the Legacy Workflow.${os_1.EOL}${os_1.EOL}${this.legacyWorkflowDeprecationMessage}`;
        this.$logger.warn(legacyWorkflowWarning, { [constants_1.LoggerConfigData.wrapMessageWithBorders]: true });
    }
    showNoBundleWarning() {
        const legacyWorkflowWarning = `You are using the '--no-bundle' flag which is switching to the Legacy Workflow.${os_1.EOL}${os_1.EOL}${this.legacyWorkflowDeprecationMessage}`;
        this.$logger.warn(legacyWorkflowWarning, { [constants_1.LoggerConfigData.wrapMessageWithBorders]: true });
    }
    ensureWebpackPluginInstalled(projectData) {
        return __awaiter(this, void 0, void 0, function* () {
            const hmrOutOfBetaWebpackPluginVersion = "0.21.0";
            const webpackPluginName = "nativescript-dev-webpack";
            const webpackConfigFileName = "webpack.config.js";
            const validWebpackPluginTags = ["*", "latest", "next", "rc"];
            let isInstalledVersionSupported = true;
            const installedVersion = this.$bundleValidatorHelper.getBundlerDependencyVersion(projectData, webpackPluginName);
            this.$logger.trace(`Updating to webpack workflow: Found ${webpackPluginName} v${installedVersion}`);
            if (validWebpackPluginTags.indexOf(installedVersion) === -1) {
                const isInstalledVersionValid = !!semver.valid(installedVersion) || !!semver.coerce(installedVersion);
                isInstalledVersionSupported =
                    isInstalledVersionValid && semver.gte(semver.coerce(installedVersion), hmrOutOfBetaWebpackPluginVersion);
                this.$logger.trace(`Updating to webpack workflow: Is installed version valid?: ${isInstalledVersionValid}`);
            }
            this.$logger.trace(`Updating to webpack workflow: Is installed version supported?: ${isInstalledVersionSupported}`);
            if (!isInstalledVersionSupported) {
                const webpackConfigPath = path.join(projectData.projectDir, webpackConfigFileName);
                if (this.$fs.exists(webpackConfigPath)) {
                    this.$fs.rename(webpackConfigPath, `${webpackConfigPath}.bak`);
                    this.$logger.warn(`The 'nativescript-dev-webpack' plugin was updated and your '${webpackConfigFileName}' was replaced. You can find your old '${webpackConfigPath}' in '${webpackConfigPath}.bak'.`);
                }
                const installResult = yield this.$packageManager.install(`${webpackPluginName}@latest`, projectData.projectDir, {
                    'save-dev': true,
                    'save-exact': true,
                    disableNpmInstall: false,
                    frameworkPath: null,
                    ignoreScripts: false,
                });
                this.$logger.trace(`Updating to webpack workflow: The ${webpackPluginName} was updated to v${installResult.version}`);
            }
        });
    }
}
exports.WorkflowService = WorkflowService;
$injector.register("workflowService", WorkflowService);
