"use strict";
var os_1 = require("os");
var semver = require("semver");
var path = require("path");
var helpers = require("../common/helpers");
var clui = require("clui");
var DoctorService = (function () {
    function DoctorService($analyticsService, $androidToolsInfo, $cocoapodsService, $hostInfo, $logger, $progressIndicator, $staticConfig, $sysInfo, $childProcess, $config, $npm, $opener, $prompter, $fs, $versionsService, $xcprojService) {
        this.$analyticsService = $analyticsService;
        this.$androidToolsInfo = $androidToolsInfo;
        this.$cocoapodsService = $cocoapodsService;
        this.$hostInfo = $hostInfo;
        this.$logger = $logger;
        this.$progressIndicator = $progressIndicator;
        this.$staticConfig = $staticConfig;
        this.$sysInfo = $sysInfo;
        this.$childProcess = $childProcess;
        this.$config = $config;
        this.$npm = $npm;
        this.$opener = $opener;
        this.$prompter = $prompter;
        this.$fs = $fs;
        this.$versionsService = $versionsService;
        this.$xcprojService = $xcprojService;
    }
    DoctorService.prototype.printWarnings = function (configOptions) {
        var _this = this;
        return (function () {
            var result = false;
            var sysInfo = _this.$sysInfo.getSysInfo(_this.$staticConfig.pathToPackageJson).wait();
            if (!sysInfo.adbVer) {
                _this.$logger.warn("WARNING: adb from the Android SDK is not installed or is not configured properly.");
                _this.$logger.out("For Android-related operations, the NativeScript CLI will use a built-in version of adb." + os_1.EOL
                    + "To avoid possible issues with the native Android emulator, Genymotion or connected" + os_1.EOL
                    + "Android devices, verify that you have installed the latest Android SDK and" + os_1.EOL
                    + "its dependencies as described in http://developer.android.com/sdk/index.html#Requirements" + os_1.EOL);
                _this.printPackageManagerTip();
                result = true;
            }
            if (!sysInfo.androidInstalled) {
                _this.$logger.warn("WARNING: The Android SDK is not installed or is not configured properly.");
                _this.$logger.out("You will not be able to build your projects for Android and run them in the native emulator." + os_1.EOL
                    + "To be able to build for Android and run apps in the native emulator, verify that you have" + os_1.EOL
                    + "installed the latest Android SDK and its dependencies as described in http://developer.android.com/sdk/index.html#Requirements" + os_1.EOL);
                _this.printPackageManagerTip();
                result = true;
            }
            if (_this.$hostInfo.isDarwin) {
                if (!sysInfo.xcodeVer) {
                    _this.$logger.warn("WARNING: Xcode is not installed or is not configured properly.");
                    _this.$logger.out("You will not be able to build your projects for iOS or run them in the iOS Simulator." + os_1.EOL
                        + "To be able to build for iOS and run apps in the native emulator, verify that you have installed Xcode." + os_1.EOL);
                    result = true;
                }
                if (!sysInfo.xcodeprojGemLocation) {
                    _this.$logger.warn("WARNING: xcodeproj gem is not installed or is not configured properly.");
                    _this.$logger.out("You will not be able to build your projects for iOS." + os_1.EOL
                        + "To be able to build for iOS and run apps in the native emulator, verify that you have installed xcodeproj." + os_1.EOL);
                    result = true;
                }
                if (!sysInfo.cocoapodVer) {
                    _this.$logger.warn("WARNING: CocoaPods is not installed or is not configured properly.");
                    _this.$logger.out("You will not be able to build your projects for iOS if they contain plugin with CocoaPod file." + os_1.EOL
                        + "To be able to build such projects, verify that you have installed CocoaPods.");
                    result = true;
                }
                if (sysInfo.xcodeVer && sysInfo.cocoapodVer) {
                    var problemWithCocoaPods = _this.verifyCocoaPods();
                    if (problemWithCocoaPods) {
                        _this.$logger.warn("WARNING: There was a problem with CocoaPods");
                        _this.$logger.out("Verify that CocoaPods are configured properly.");
                        result = true;
                    }
                }
                if (sysInfo.cocoapodVer && semver.valid(sysInfo.cocoapodVer) && semver.lt(sysInfo.cocoapodVer, DoctorService.MIN_SUPPORTED_POD_VERSION)) {
                    _this.$logger.warn("WARNING: Your current CocoaPods version is earlier than " + DoctorService.MIN_SUPPORTED_POD_VERSION + ".");
                    _this.$logger.out("You will not be able to build your projects for iOS if they contain plugin with CocoaPod file." + os_1.EOL
                        + ("To be able to build such projects, verify that you have at least " + DoctorService.MIN_SUPPORTED_POD_VERSION + " version installed."));
                    result = true;
                }
                if (_this.$xcprojService.verifyXcproj(false).wait()) {
                    result = true;
                }
            }
            else {
                _this.$logger.out("NOTE: You can develop for iOS only on Mac OS X systems.");
                _this.$logger.out("To be able to work with iOS devices and projects, you need Mac OS X Mavericks or later." + os_1.EOL);
            }
            var androidToolsIssues = _this.$androidToolsInfo.validateInfo().wait();
            var javaVersionIssue = _this.$androidToolsInfo.validateJavacVersion(sysInfo.javacVersion).wait();
            var doctorResult = result || androidToolsIssues || javaVersionIssue;
            if (!configOptions || configOptions.trackResult) {
                _this.$analyticsService.track("DoctorEnvironmentSetup", doctorResult ? "incorrect" : "correct").wait();
            }
            if (doctorResult) {
                _this.$logger.info("There seem to be issues with your configuration.");
                if (_this.$hostInfo.isDarwin) {
                    _this.promptForHelp(DoctorService.DarwinSetupDocsLink, DoctorService.DarwinSetupScriptLocation, []).wait();
                }
                else if (_this.$hostInfo.isWindows) {
                    _this.promptForHelp(DoctorService.WindowsSetupDocsLink, DoctorService.WindowsSetupScriptExecutable, DoctorService.WindowsSetupScriptArguments).wait();
                }
                else {
                    _this.promptForDocs(DoctorService.LinuxSetupDocsLink).wait();
                }
            }
            var versionsInformation = [];
            try {
                versionsInformation = _this.$versionsService.getComponentsForUpdate().wait();
                _this.printVersionsInformation(versionsInformation);
            }
            catch (err) {
                _this.$logger.error("Cannot get the latest versions information from npm. Please try again later.");
            }
            return doctorResult;
        }).future()();
    };
    DoctorService.prototype.printVersionsInformation = function (versionsInformation) {
        if (versionsInformation && versionsInformation.length) {
            var table = this.$versionsService.createTableWithVersionsInformation(versionsInformation);
            this.$logger.warn("Updates available");
            this.$logger.out(table.toString() + os_1.EOL);
        }
        else {
            this.$logger.out("Your components are up-to-date." + os_1.EOL);
        }
    };
    DoctorService.prototype.promptForDocs = function (link) {
        var _this = this;
        return (function () {
            if (_this.$prompter.confirm("Do you want to visit the official documentation?", function () { return helpers.isInteractive(); }).wait()) {
                _this.$opener.open(link);
            }
        }).future()();
    };
    DoctorService.prototype.promptForHelp = function (link, commandName, commandArguments) {
        var _this = this;
        return (function () {
            _this.promptForDocs(link).wait();
            if (_this.$prompter.confirm("Do you want to run the setup script?", function () { return helpers.isInteractive(); }).wait()) {
                _this.$childProcess.spawnFromEvent(commandName, commandArguments, "close", { stdio: "inherit" }).wait();
            }
        }).future()();
    };
    DoctorService.prototype.printPackageManagerTip = function () {
        if (this.$hostInfo.isWindows) {
            this.$logger.out("TIP: To avoid setting up the necessary environment variables, you can use the chocolatey package manager to install the Android SDK and its dependencies." + os_1.EOL);
        }
        else if (this.$hostInfo.isDarwin) {
            this.$logger.out("TIP: To avoid setting up the necessary environment variables, you can use the Homebrew package manager to install the Android SDK and its dependencies." + os_1.EOL);
        }
    };
    DoctorService.prototype.verifyCocoaPods = function () {
        this.$logger.out("Verifying CocoaPods. This may take more than a minute, please be patient.");
        var temp = require("temp");
        temp.track();
        var projDir = temp.mkdirSync("nativescript-check-cocoapods");
        var packageJsonData = {
            "name": "nativescript-check-cocoapods",
            "version": "0.0.1"
        };
        this.$fs.writeJson(path.join(projDir, "package.json"), packageJsonData).wait();
        var spinner = new clui.Spinner("Installing iOS runtime.");
        try {
            spinner.start();
            this.$npm.install("tns-ios", projDir, { "ignore-scripts": true, production: true, save: true }).wait();
            spinner.stop();
            var iosDir = path.join(projDir, "node_modules", "tns-ios", "framework");
            this.$fs.writeFile(path.join(iosDir, "Podfile"), this.$cocoapodsService.getPodfileHeader(DoctorService.PROJECT_NAME_PLACEHOLDER) + "pod 'AFNetworking', '~> 1.0'" + this.$cocoapodsService.getPodfileFooter()).wait();
            spinner.message("Verifying CocoaPods. This may take some time, please be patient.");
            spinner.start();
            var future = this.$childProcess.spawnFromEvent(this.$config.USE_POD_SANDBOX ? "sandbox-pod" : "pod", ["install"], "exit", { cwd: iosDir }, { throwError: false });
            this.$progressIndicator.showProgressIndicator(future, 5000).wait();
            var result = future.get();
            if (result.exitCode) {
                this.$logger.out(result.stdout, result.stderr);
                return true;
            }
            return !(this.$fs.exists(path.join(iosDir, DoctorService.PROJECT_NAME_PLACEHOLDER + ".xcworkspace")).wait());
        }
        catch (err) {
            this.$logger.trace("verifyCocoaPods error: " + err);
            return true;
        }
        finally {
            spinner.stop();
        }
    };
    DoctorService.PROJECT_NAME_PLACEHOLDER = "__PROJECT_NAME__";
    DoctorService.MIN_SUPPORTED_POD_VERSION = "1.0.0";
    DoctorService.DarwinSetupScriptLocation = path.join(__dirname, "..", "..", "setup", "mac-startup-shell-script.sh");
    DoctorService.DarwinSetupDocsLink = "https://docs.nativescript.org/start/ns-setup-os-x";
    DoctorService.WindowsSetupScriptExecutable = "powershell.exe";
    DoctorService.WindowsSetupScriptArguments = ["start-process", "-FilePath", "PowerShell.exe", "-NoNewWindow", "-Wait", "-ArgumentList", '"-NoProfile -ExecutionPolicy Bypass -Command iex ((new-object net.webclient).DownloadString(\'https://raw.githubusercontent.com/NativeScript/nativescript-cli/production/setup/native-script.ps1\'))"'];
    DoctorService.WindowsSetupDocsLink = "https://docs.nativescript.org/start/ns-setup-win";
    DoctorService.LinuxSetupDocsLink = "https://docs.nativescript.org/start/ns-setup-linux";
    return DoctorService;
}());
$injector.register("doctorService", DoctorService);
