"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandDispatcher = void 0;
const _ = require("lodash");
const queue = require("./queue");
const path = require("path");
const helpers_1 = require("./helpers");
const yok_1 = require("./yok");
const constants_1 = require("../constants");
const semver = require("semver");
class CommandDispatcher {
    constructor($logger, 
    // required by the hooksService
    $injector, $cancellation, $commandsService, $staticConfig, $sysInfo, $options, $versionsService, $packageManager, $terminalSpinnerService) {
        this.$logger = $logger;
        this.$injector = $injector;
        this.$cancellation = $cancellation;
        this.$commandsService = $commandsService;
        this.$staticConfig = $staticConfig;
        this.$sysInfo = $sysInfo;
        this.$options = $options;
        this.$versionsService = $versionsService;
        this.$packageManager = $packageManager;
        this.$terminalSpinnerService = $terminalSpinnerService;
    }
    dispatchCommand() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.$options.version) {
                return this.printVersion();
            }
            if (this.$logger.getLevel() === "TRACE" && !this.$options.json) {
                // CommandDispatcher is called from external CLI's only, so pass the path to their package.json
                this.$logger.trace("Collecting system information...");
                const sysInfo = yield this.$sysInfo.getSysInfo({
                    pathToNativeScriptCliPackageJson: path.join(__dirname, "..", "..", "package.json"),
                });
                this.$logger.trace("System information:");
                this.$logger.trace(JSON.stringify(sysInfo, null, 2));
                this.$logger.trace("Current CLI version: ", this.$staticConfig.version);
            }
            let commandName = this.getCommandName();
            let commandArguments = this.$options.argv._.slice(1);
            const lastArgument = _.last(commandArguments);
            if (this.$options.help) {
                commandArguments.unshift(commandName);
                commandName = "help";
            }
            else if (lastArgument === "/?" || lastArgument === "?") {
                commandArguments.pop();
                commandArguments.unshift(commandName);
                commandName = "help";
            }
            ({
                commandName,
                commandArguments,
                argv: process.argv,
            } = yield this.resolveCommand(commandName, commandArguments, process.argv));
            yield this.$cancellation.begin("cli");
            yield this.$commandsService.tryExecuteCommand(commandName, commandArguments);
        });
    }
    resolveCommand(commandName, commandArguments, argv) {
        return __awaiter(this, void 0, void 0, function* () {
            // just a hook point
            return { commandName, commandArguments, argv };
        });
    }
    getCommandName() {
        const remaining = this.$options.argv._;
        if (remaining.length > 0) {
            return remaining[0].toString().toLowerCase();
        }
        // if only <CLI_NAME> is specified on console, show console help
        this.$options.help = true;
        return "";
    }
    printVersion() {
        return __awaiter(this, void 0, void 0, function* () {
            this.$logger.info(this.$staticConfig.version);
            if (this.$options.json) {
                // we don't check for updates when --json is passed
                // useful for tools that rely on the output of the command
                return;
            }
            const spinner = this.$terminalSpinnerService.createSpinner();
            spinner.start("Checking for updates...");
            const nativescriptCliVersion = yield this.$versionsService.getNativescriptCliVersion();
            spinner.stop();
            const packageManagerName = yield this.$packageManager.getPackageManagerName();
            let updateCommand = "";
            switch (packageManagerName) {
                case constants_1.PackageManagers.yarn:
                case constants_1.PackageManagers.yarn2:
                    updateCommand = "yarn global add nativescript";
                    break;
                case constants_1.PackageManagers.pnpm:
                    updateCommand = "pnpm i -g nativescript";
                    break;
                case constants_1.PackageManagers.bun:
                    updateCommand = "bun add --global nativescript";
                    break;
                case constants_1.PackageManagers.npm:
                default:
                    updateCommand = "npm i -g nativescript";
                    break;
            }
            if (semver.gte(nativescriptCliVersion.currentVersion, nativescriptCliVersion.latestVersion, {
                loose: true,
            })) {
                // up-to-date
                spinner.succeed("Up to date.");
            }
            else {
                spinner.info(`New version of NativeScript CLI is available (${nativescriptCliVersion.latestVersion}), run '${updateCommand}' to update.`);
            }
        });
    }
}
__decorate([
    (0, helpers_1.hook)("resolveCommand")
], CommandDispatcher.prototype, "resolveCommand", null);
exports.CommandDispatcher = CommandDispatcher;
yok_1.injector.register("commandDispatcher", CommandDispatcher);
class FutureDispatcher {
    constructor($errors) {
        this.$errors = $errors;
    }
    run() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.actions) {
                this.$errors.fail("You cannot run a running future dispatcher.");
            }
            this.actions = new queue.Queue();
            while (true) {
                const action = yield this.actions.dequeue();
                yield action();
            }
        });
    }
    dispatch(action) {
        this.actions.enqueue(action);
    }
}
yok_1.injector.register("dispatcher", FutureDispatcher, false);
//# sourceMappingURL=dispatchers.js.map