"use strict";
var path = require("path");
var semver = require("semver");
var constants = require("./constants");
var NpmInstallationManager = (function () {
    function NpmInstallationManager($npm, $logger, $errors, $options, $fs, $staticConfig) {
        this.$npm = $npm;
        this.$logger = $logger;
        this.$errors = $errors;
        this.$options = $options;
        this.$fs = $fs;
        this.$staticConfig = $staticConfig;
    }
    NpmInstallationManager.prototype.getLatestVersion = function (packageName) {
        var _this = this;
        return (function () {
            return _this.getVersion(packageName, constants.PackageVersion.LATEST).wait();
        }).future()();
    };
    NpmInstallationManager.prototype.getNextVersion = function (packageName) {
        var _this = this;
        return (function () {
            return _this.getVersion(packageName, constants.PackageVersion.NEXT).wait();
        }).future()();
    };
    NpmInstallationManager.prototype.getLatestCompatibleVersion = function (packageName) {
        var _this = this;
        return (function () {
            var cliVersionRange = "~" + _this.$staticConfig.version;
            var latestVersion = _this.getLatestVersion(packageName).wait();
            if (semver.satisfies(latestVersion, cliVersionRange)) {
                return latestVersion;
            }
            var data = _this.$npm.view(packageName, { json: true, "versions": true }).wait();
            return semver.maxSatisfying(data, cliVersionRange) || latestVersion;
        }).future()();
    };
    NpmInstallationManager.prototype.install = function (packageName, projectDir, opts) {
        var _this = this;
        return (function () {
            try {
                var packageToInstall = _this.$options.frameworkPath || packageName;
                var pathToSave = projectDir;
                var version = (opts && opts.version) || null;
                var dependencyType = (opts && opts.dependencyType) || null;
                return _this.installCore(packageToInstall, pathToSave, version, dependencyType).wait();
            }
            catch (error) {
                _this.$logger.debug(error);
                _this.$errors.fail("%s. Error: %s", NpmInstallationManager.NPM_LOAD_FAILED, error);
            }
        }).future()();
    };
    NpmInstallationManager.prototype.installCore = function (packageName, pathToSave, version, dependencyType) {
        var _this = this;
        return (function () {
            var possiblePackageName = path.resolve(packageName);
            if (_this.$fs.exists(possiblePackageName).wait()) {
                packageName = possiblePackageName;
            }
            if (packageName.indexOf(".tgz") >= 0) {
                version = null;
            }
            if (_this.isURL(packageName) || _this.$fs.exists(packageName).wait()) {
                version = null;
            }
            else {
                version = version || _this.getLatestCompatibleVersion(packageName).wait();
            }
            var installedModuleNames = _this.npmInstall(packageName, pathToSave, version, dependencyType).wait();
            var installedPackageName = installedModuleNames[0];
            var pathToInstalledPackage = path.join(pathToSave, "node_modules", installedPackageName);
            return pathToInstalledPackage;
        }).future()();
    };
    NpmInstallationManager.prototype.isURL = function (str) {
        var urlRegex = '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$';
        var url = new RegExp(urlRegex, 'i');
        return str.length < 2083 && url.test(str);
    };
    NpmInstallationManager.prototype.npmInstall = function (packageName, pathToSave, version, dependencyType) {
        var _this = this;
        return (function () {
            _this.$logger.out("Installing ", packageName);
            packageName = packageName + (version ? "@" + version : "");
            var npmOptions = { silent: true };
            if (dependencyType) {
                npmOptions[dependencyType] = true;
            }
            return _this.$npm.install(packageName, pathToSave, npmOptions).wait();
        }).future()();
    };
    NpmInstallationManager.prototype.getVersion = function (packageName, version) {
        var _this = this;
        return (function () {
            var data = _this.$npm.view(packageName, { json: true, "dist-tags": true }).wait();
            _this.$logger.trace("Using version %s. ", data[version]);
            return data[version];
        }).future()();
    };
    NpmInstallationManager.NPM_LOAD_FAILED = "Failed to retrieve data from npm. Please try again a little bit later.";
    return NpmInstallationManager;
}());
exports.NpmInstallationManager = NpmInstallationManager;
$injector.register("npmInstallationManager", NpmInstallationManager);
