"use strict";
var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var parse5 = require("parse5");
var plugins_source_base_1 = require("./plugins-source-base");
var NpmjsPluginsSource = (function (_super) {
    __extends(NpmjsPluginsSource, _super);
    function NpmjsPluginsSource($progressIndicator, $logger, $httpClient, $childProcess, $hostInfo, $errors) {
        _super.call(this, $progressIndicator, $logger);
        this.$httpClient = $httpClient;
        this.$childProcess = $childProcess;
        this.$hostInfo = $hostInfo;
        this.$errors = $errors;
        this._pages = [];
    }
    Object.defineProperty(NpmjsPluginsSource.prototype, "progressIndicatorMessage", {
        get: function () {
            return "Searching for plugins in http://npmjs.org.";
        },
        enumerable: true,
        configurable: true
    });
    NpmjsPluginsSource.prototype.getPlugins = function (page, count) {
        var _this = this;
        return (function () {
            var loadedPlugins = _this._pages[page];
            if (loadedPlugins) {
                return loadedPlugins;
            }
            var result = _this.getPluginsFromNpmjs(_this._keywords, page).wait();
            _this._pages[page] = result;
            _this.plugins = _this.plugins.concat(result);
            return result;
        }).future()();
    };
    NpmjsPluginsSource.prototype.getAllPlugins = function () {
        var _this = this;
        return (function () {
            var getAllPluginsFuture = _this.getAllPluginsCore();
            _this.$logger.printInfoMessageOnSameLine("Getting all results, please wait.");
            _this.$progressIndicator.showProgressIndicator(getAllPluginsFuture, 2000).wait();
            return getAllPluginsFuture.get();
        }).future()();
    };
    NpmjsPluginsSource.prototype.initializeCore = function (projectDir, keywords) {
        var _this = this;
        return (function () {
            _this._keywords = keywords;
            _this.plugins = _this.getPluginsFromNpmjs(keywords, 1).wait();
        }).future()();
    };
    NpmjsPluginsSource.prototype.getAllPluginsCore = function () {
        var _this = this;
        return (function () {
            var result = [];
            var currentPluginsFound = [];
            var page = 0;
            do {
                currentPluginsFound = _this.getPluginsFromNpmjs(_this._keywords, page++).wait();
                if (currentPluginsFound && currentPluginsFound.length) {
                    result = result.concat(currentPluginsFound);
                }
            } while (currentPluginsFound && currentPluginsFound.length);
            return result;
        }).future()();
    };
    NpmjsPluginsSource.prototype.getPluginsFromNpmjs = function (keywords, page) {
        var _this = this;
        return (function () {
            var pluginName = encodeURIComponent(keywords.join(" "));
            var url = NpmjsPluginsSource.NPMJS_ADDRESS + "/search?q=" + pluginName + "&page=" + page;
            try {
                var responseBody = _this.$httpClient.httpRequest(url).wait().body;
                var document_1 = parse5.parse(responseBody);
                var html = _.find(document_1.childNodes, function (node) { return node.nodeName === "html"; });
                var resultsContainer = _this.findNodeByClass(html, "search-results");
                if (!resultsContainer || !resultsContainer.childNodes) {
                    return null;
                }
                var resultsElements = _.filter(resultsContainer.childNodes, function (node) { return node.nodeName === "li"; });
                return _.map(resultsElements, function (node) { return _this.getPluginInfo(node); });
            }
            catch (err) {
                _this.$logger.trace("Error while getting information for " + keywords + " from http://npmjs.org - " + err);
                return null;
            }
        }).future()();
    };
    NpmjsPluginsSource.prototype.getPluginInfo = function (node) {
        var name = this.getTextFromElementWithClass(node, "name");
        var version = this.getTextFromElementWithClass(node, "version");
        var description = this.getTextFromElementWithClass(node, "description");
        var author = this.getTextFromElementWithClass(node, "author");
        return {
            name: name,
            version: version,
            description: description,
            author: author
        };
    };
    NpmjsPluginsSource.prototype.findNodeByClass = function (parent, className) {
        if (!parent.childNodes || parent.childNodes.length === 0) {
            return null;
        }
        for (var i = 0; i < parent.childNodes.length; i++) {
            var node = parent.childNodes[i];
            if (_.some(node.attrs, function (attr) { return attr.name === "class" && attr.value === className; })) {
                return node;
            }
            else {
                var result = this.findNodeByClass(node, className);
                if (result) {
                    return result;
                }
            }
        }
    };
    NpmjsPluginsSource.prototype.getTextFromElementWithClass = function (node, className) {
        var element = this.findNodeByClass(node, className);
        if (element && element.childNodes) {
            var textElement = _.find(element.childNodes, function (child) { return child.nodeName === "#text"; });
            if (textElement) {
                return textElement.value;
            }
        }
        return null;
    };
    NpmjsPluginsSource.NPMJS_ADDRESS = "http://npmjs.org";
    return NpmjsPluginsSource;
}(plugins_source_base_1.PluginsSourceBase));
exports.NpmjsPluginsSource = NpmjsPluginsSource;
