"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandScope = void 0;
const Log_1 = require("../core/Log");
const Utilities_1 = require("../core/Utilities");
const CommandStructure_1 = require("./CommandStructure");
const ICommand_1 = require("./ICommand");
var CommandScope;
(function (CommandScope) {
    CommandScope[CommandScope["any"] = 1] = "any";
    CommandScope[CommandScope["project"] = 2] = "project";
    CommandScope[CommandScope["minecraft"] = 3] = "minecraft";
    CommandScope[CommandScope["carto"] = 4] = "carto";
    CommandScope[CommandScope["host"] = 5] = "host";
    CommandScope[CommandScope["debug"] = 10] = "debug";
    CommandScope[CommandScope["debugProject"] = 11] = "debugProject";
    CommandScope[CommandScope["debugMinecraft"] = 12] = "debugMinecraft";
    CommandScope[CommandScope["debugHost"] = 14] = "debugHost";
})(CommandScope = exports.CommandScope || (exports.CommandScope = {}));
const MinecraftCommands = [
    "aimassist",
    "allowlist",
    "alwaysday",
    "camera",
    "camerashake",
    "changesetting",
    "clear",
    "clearspawnpoint",
    "clone",
    "connect",
    "controlscheme",
    "damage",
    "daylock",
    "deop",
    "dialogue",
    "difficulty",
    "effect",
    "enchant",
    "event",
    "execute",
    "fill",
    "fog",
    "function",
    "gamemode",
    "gamerule",
    "gametest",
    "give",
    "help",
    "hud",
    "inputpermission",
    "kick",
    "kill",
    "list",
    "locate",
    "loot",
    "me",
    "msg",
    "mobevent",
    "music",
    "op",
    "ops",
    "particle",
    "permission",
    "place",
    "playanimation",
    "playsound",
    "project",
    "recipe",
    "reload",
    "reloadconfig",
    "reloadpacketlimitconfig",
    "replaceitem",
    "ride",
    "save",
    "say",
    "schedule",
    "scoreboard",
    "script",
    "scriptevent",
    "sendshowstoreoffer",
    "setblock",
    "setmaxplayers",
    "setworldspawn",
    "simulationtype",
    "spawnpoint",
    "spreadplayers",
    "stop",
    "stopsound",
    "structure",
    "summon",
    "tag",
    "teleport",
    "tell",
    "tellraw",
    "testfor",
    "testforblock",
    "testforblocks",
    "tickingarea",
    "tp",
    "time",
    "title",
    "titleraw",
    "toggledownfall",
    "transfer",
    "volumearea",
    "weather",
    "wsserver",
    "whitelist",
    "?",
    "w",
    "xp",
];
const MinecraftAddOnBlockedCommands = [
    "allowlist",
    "alwaysday",
    "changesetting",
    "connect",
    "daylock",
    "deop",
    "difficulty",
    "gamemode",
    "gamerule",
    "gametest",
    "help",
    "kick",
    "list",
    "locate",
    "op",
    "ops",
    "permission",
    "project",
    "reload",
    "reloadconfig",
    "save",
    "script",
    "setmaxplayers",
    "setworldspawn",
    "simulationtype",
    "stop",
    "tickingarea",
    "time",
    "transfer",
    "wsserver",
    "whitelist",
    "?",
];
class CommandRegistry {
    static _registry;
    _commandsByName = {};
    _commandsByScope = {};
    static get main() {
        if (!this._registry) {
            this._registry = new CommandRegistry();
            this._registry.registerCommand("sleep", CommandScope.any, async (context, name, args) => {
                if (args.length === 1) {
                    let delay = 0;
                    try {
                        delay = parseInt(args[0]);
                    }
                    catch (e) { }
                    if (delay > 0) {
                        context.carto.notifyStatusUpdate("(Delaying commands for " + delay + "ms).");
                        await Utilities_1.default.sleep(delay);
                    }
                }
                return { status: ICommand_1.CommandStatus.completed };
            });
        }
        return this._registry;
    }
    registerCommand(commandName, commandScope, command) {
        commandName = commandName.toLowerCase();
        if (Utilities_1.default.isUsableAsObjectKey(commandName)) {
            this._commandsByName[commandName] = command;
            this._commandsByScope[commandName] = commandScope;
        }
        else {
            Log_1.default.unsupportedToken(commandName);
        }
    }
    logHelp() {
        let commandArr = [];
        for (const commandName in this._commandsByName) {
            commandArr.push(commandName);
        }
        commandArr = commandArr.sort();
        Log_1.default.message("Use help <command name> for more detailed help on a command.");
        for (let i = 0; i < commandArr.length; i++) {
            Log_1.default.message(commandArr[i]);
        }
    }
    static isMinecraftBuiltInCommand(name) {
        return MinecraftCommands.includes(name) || name === "#";
    }
    static isAddOnBlockedCommand(name) {
        return MinecraftAddOnBlockedCommands.includes(name);
    }
    async runCommand(context, commandText) {
        const command = CommandStructure_1.default.parse(commandText);
        if (!command || !command.name || !command.commandArguments) {
            return undefined;
        }
        const scope = this._commandsByScope[command.name];
        const commandName = this._commandsByName[command.name];
        if (command.name === "help") {
            this.logHelp();
            return { status: ICommand_1.CommandStatus.completed };
        }
        else if (CommandRegistry.isMinecraftBuiltInCommand(command.name) && context.minecraft) {
            Log_1.default.debug("Sending '" + commandText + "' to Minecraft.");
            let result = await context.minecraft.runCommand(commandText);
            return {
                data: result,
                status: ICommand_1.CommandStatus.completed,
            };
        }
        else if (scope && commandName) {
            if ((scope === CommandScope.debug ||
                scope === CommandScope.debugProject ||
                scope === CommandScope.debugMinecraft) &&
                !Utilities_1.default.isDebug) {
                return undefined;
            }
            if ((scope === CommandScope.project || scope === CommandScope.debugProject) && !context.project) {
                Log_1.default.message("Could not run command '" + command.name + "'; no active project.");
                return undefined;
            }
            if ((scope === CommandScope.minecraft || scope === CommandScope.debugMinecraft) && !context.minecraft) {
                Log_1.default.message("Could not run command '" + command.name + "'; no active Minecraft deploy target was set.");
                return undefined;
            }
            if ((scope === CommandScope.host || scope === CommandScope.debugHost) && !context.host) {
                Log_1.default.message("Could not run command '" + command.name + "'; no host was set.");
                return undefined;
            }
            const result = await commandName(context, command.name, command.commandArguments);
            if (result.status === ICommand_1.CommandStatus.invalidEnvironment) {
                Log_1.default.error("'" + command.name + "' was not set up properly.");
            }
            else if (result.status === ICommand_1.CommandStatus.invalidArguments) {
                Log_1.default.error("'" + command.name + "' command arguments were not set up.");
            }
            return result;
        }
        context.carto.notifyStatusUpdate("Could not find a command '" + command.name + "'.");
        return undefined;
    }
}
exports.default = CommandRegistry;

//# sourceMappingURL=../maps/app/CommandRegistry.js.map
