"use strict";
var path = require("path");
var NodePackageManager = (function () {
    function NodePackageManager($fs, $hostInfo, $errors, $childProcess, $logger, $options) {
        this.$fs = $fs;
        this.$hostInfo = $hostInfo;
        this.$errors = $errors;
        this.$childProcess = $childProcess;
        this.$logger = $logger;
        this.$options = $options;
    }
    NodePackageManager.prototype.install = function (packageName, pathToSave, config) {
        var _this = this;
        return (function () {
            if (_this.$options.disableNpmInstall) {
                return;
            }
            if (_this.$options.ignoreScripts) {
                config = config || {};
                config["ignore-scripts"] = true;
            }
            var jsonContentBefore = _this.$fs.readJson(path.join(pathToSave, "package.json")).wait();
            var dependenciesBefore = _.keys(jsonContentBefore.dependencies).concat(_.keys(jsonContentBefore.devDependencies));
            var flags = _this.getFlagsString(config, true);
            var params = ["install"];
            if (packageName !== pathToSave) {
                params.push(packageName);
            }
            params = params.concat(flags);
            var pwd = pathToSave;
            if (_this.$options.path) {
                var relativePathFromCwdToSource = "";
                if (_this.$options.frameworkPath) {
                    relativePathFromCwdToSource = path.relative(_this.$options.frameworkPath, pathToSave);
                    if (_this.$fs.exists(relativePathFromCwdToSource).wait()) {
                        packageName = relativePathFromCwdToSource;
                    }
                }
            }
            try {
                var spawnResult = _this.$childProcess.spawnFromEvent(_this.getNpmExecutableName(), params, "close", { cwd: pwd }).wait();
                _this.$logger.out(spawnResult.stdout);
            }
            catch (err) {
                if (err.message && err.message.indexOf("EPEERINVALID") !== -1) {
                    _this.$logger.warn(err.message);
                }
                else {
                    throw err;
                }
            }
            var jsonContentAfter = _this.$fs.readJson(path.join(pathToSave, "package.json")).wait();
            var dependenciesAfter = _.keys(jsonContentAfter.dependencies).concat(_.keys(jsonContentAfter.devDependencies));
            var dependencyDiff = _(jsonContentAfter.dependencies)
                .omitBy(function (val, key) { return jsonContentBefore && jsonContentBefore.dependencies && jsonContentBefore.dependencies[key] && jsonContentBefore.dependencies[key] === val; })
                .keys()
                .value();
            var devDependencyDiff = _(jsonContentAfter.devDependencies)
                .omitBy(function (val, key) { return jsonContentBefore && jsonContentBefore.devDependencies && jsonContentBefore.devDependencies[key] && jsonContentBefore.devDependencies[key] === val; })
                .keys()
                .value();
            var diff = dependencyDiff.concat(devDependencyDiff);
            if (diff.length <= 0 && dependenciesBefore.length === dependenciesAfter.length && packageName !== pathToSave) {
                _this.$errors.failWithoutHelp("The plugin " + packageName + " is already installed");
            }
            if (diff.length <= 0 && dependenciesBefore.length !== dependenciesAfter.length) {
                _this.$errors.failWithoutHelp("Couldn't install package correctly");
            }
            return diff;
        }).future()();
    };
    NodePackageManager.prototype.uninstall = function (packageName, config, path) {
        var flags = this.getFlagsString(config, false);
        return this.$childProcess.exec("npm uninstall " + packageName + " " + flags, { cwd: path });
    };
    NodePackageManager.prototype.search = function (filter, config) {
        var args = ([filter] || []).concat(config.silent);
        return this.$childProcess.exec("npm search " + args.join(" "));
    };
    NodePackageManager.prototype.view = function (packageName, config) {
        var _this = this;
        return (function () {
            var flags = _this.getFlagsString(config, false);
            var viewResult;
            try {
                viewResult = _this.$childProcess.exec("npm view " + packageName + " " + flags).wait();
            }
            catch (e) {
                _this.$errors.failWithoutHelp(e);
            }
            return JSON.parse(viewResult);
        }).future()();
    };
    NodePackageManager.prototype.getNpmExecutableName = function () {
        var npmExecutableName = "npm";
        if (this.$hostInfo.isWindows) {
            npmExecutableName += ".cmd";
        }
        return npmExecutableName;
    };
    NodePackageManager.prototype.getFlagsString = function (config, asArray) {
        var array = [];
        for (var flag in config) {
            if (config[flag]) {
                if (flag === "dist-tags" || flag === "versions") {
                    array.push(" " + flag);
                    continue;
                }
                array.push("--" + flag);
            }
        }
        if (asArray) {
            return array;
        }
        return array.join(" ");
    };
    return NodePackageManager;
}());
exports.NodePackageManager = NodePackageManager;
$injector.register("npm", NodePackageManager);
