"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());
    });
};
const helpers_1 = require("../../common/helpers");
const constants_1 = require("../../constants");
class FindPluginsCommand {
    constructor($pluginsService, $logger, $prompter, $options, $progressIndicator) {
        this.$pluginsService = $pluginsService;
        this.$logger = $logger;
        this.$prompter = $prompter;
        this.$options = $options;
        this.$progressIndicator = $progressIndicator;
        this.allowedParameters = [];
    }
    execute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            let filter = this.prepareFilter(args);
            let pluginsPromise = this.$pluginsService.getAvailable(filter);
            if (this.$options.json) {
                this.$logger.out(JSON.stringify(yield pluginsPromise));
                return;
            }
            this.$logger.printInfoMessageOnSameLine("Searching npm please be patient...");
            let plugins = yield this.$progressIndicator.showProgressIndicator(pluginsPromise, 500);
            yield this.showPlugins(plugins);
        });
    }
    canExecute(args) {
        return __awaiter(this, void 0, void 0, function* () {
            return Promise.resolve(true);
        });
    }
    showPlugins(plugins) {
        return __awaiter(this, void 0, void 0, function* () {
            let allPluginsNames = _.keys(plugins).sort();
            if (!allPluginsNames || !allPluginsNames.length) {
                this.$logger.warn("No plugins found.");
                return;
            }
            let count = this.$options.count || FindPluginsCommand.COUNT_OF_PLUGINS_TO_DISPLAY;
            if (!helpers_1.isInteractive() || this.$options.all) {
                count = allPluginsNames.length;
            }
            let data = [];
            let pluginsToDisplay = allPluginsNames.splice(0, count);
            let shouldDisplayMorePlugins = true;
            this.$logger.out("Available NativeScript plugins:");
            do {
                data = this.createTableCells(plugins, pluginsToDisplay);
                let table = this.createPluginsTable(data);
                this.$logger.out(table.toString());
                pluginsToDisplay = allPluginsNames.splice(0, count);
                if (!pluginsToDisplay || pluginsToDisplay.length < 1) {
                    return;
                }
                shouldDisplayMorePlugins = yield this.$prompter.confirm("Load more plugins?");
            } while (shouldDisplayMorePlugins);
        });
    }
    createPluginsTable(data) {
        let headers = ["Plugin", "Version", "Description"];
        let table = helpers_1.createTable(headers, data);
        return table;
    }
    createTableCells(plugins, pluginsToDisplay) {
        return pluginsToDisplay.map(pluginName => {
            let pluginDetails = plugins[pluginName];
            return [pluginName, pluginDetails.version, pluginDetails.description || ""];
        });
    }
    prepareFilter(args) {
        return _(args || [])
            .map(arg => arg.toLowerCase())
            .concat(constants_1.NATIVESCRIPT_KEY_NAME)
            .uniq()
            .value();
    }
}
FindPluginsCommand.COUNT_OF_PLUGINS_TO_DISPLAY = 10;
exports.FindPluginsCommand = FindPluginsCommand;
$injector.registerCommand(["plugin|find", "plugin|search"], FindPluginsCommand);
