"use strict";
const queue = require("./queue");
const path = require("path");
class CommandDispatcher {
    constructor($logger, $cancellation, $commandsService, $staticConfig, $sysInfo, $options, $fs) {
        this.$logger = $logger;
        this.$cancellation = $cancellation;
        this.$commandsService = $commandsService;
        this.$staticConfig = $staticConfig;
        this.$sysInfo = $sysInfo;
        this.$options = $options;
        this.$fs = $fs;
    }
    dispatchCommand() {
        return (() => {
            if (this.$options.version) {
                return this.printVersion();
            }
            if (this.$logger.getLevel() === "TRACE") {
                let sysInfo = this.$sysInfo.getSysInfo(path.join(__dirname, "..", "..", "package.json")).wait();
                this.$logger.trace("System information:");
                this.$logger.trace(sysInfo);
            }
            let commandName = this.getCommandName();
            let commandArguments = this.$options.argv._.slice(1);
            let lastArgument = _.last(commandArguments);
            if (this.$options.help) {
                commandArguments.unshift(commandName);
                commandName = "help";
            }
            else if (lastArgument === "/?" || lastArgument === "?") {
                commandArguments.pop();
                commandArguments.unshift(commandName);
                commandName = "help";
            }
            this.$cancellation.begin("cli").wait();
            this.$commandsService.tryExecuteCommand(commandName, commandArguments).wait();
        }).future()();
    }
    completeCommand() {
        return this.$commandsService.completeCommand();
    }
    getCommandName() {
        let remaining = this.$options.argv._;
        if (remaining.length > 0) {
            return remaining[0].toString().toLowerCase();
        }
        this.$options.help = true;
        return "";
    }
    printVersion() {
        let version = this.$staticConfig.version;
        let json = this.$fs.readJson(this.$staticConfig.pathToPackageJson).wait();
        if (json && json.buildVersion) {
            version = `${version}-${json.buildVersion}`;
        }
        this.$logger.out(version);
    }
}
exports.CommandDispatcher = CommandDispatcher;
$injector.register("commandDispatcher", CommandDispatcher);
class FutureDispatcher {
    constructor($errors) {
        this.$errors = $errors;
    }
    run() {
        if (this.actions) {
            this.$errors.fail("You cannot run a running future dispatcher.");
        }
        this.actions = new queue.Queue();
        while (true) {
            let action = this.actions.dequeue().wait();
            action().wait();
        }
    }
    dispatch(action) {
        this.actions.enqueue(action);
    }
}
$injector.register("dispatcher", FutureDispatcher, false);
