import LookCommand from "./commands/look";
import UseCommand from "./commands/use";
import TakeCommand from "./commands/take";
import DropCommand from "./commands/drop";
import EchoCommand from "./commands/echo";
import SaveCommand from "./commands/save";
import LoadCommand from "./commands/load";
import VolumeCommand from "./commands/volume";
import InventoryCommand from "./commands/inventory";

const defaultCommands = [
    LookCommand,
    UseCommand,
    TakeCommand,
    DropCommand,
    EchoCommand,
    SaveCommand,
    LoadCommand,
    VolumeCommand,
    InventoryCommand
];

const directionMap = [
    ["n", "north"],
    ["ne", "northeast"],
    ["e", "east"],
    ["se", "southeast"],
    ["s", "south"],
    ["sw", "southwest"],
    ["w", "west"],
    ["nw", "northwest"],
    ["u", "up"],
    ["d", "down"]
];

export default class Commands {
    constructor(context, commands) {
        this.context = context;
        this.commands = commands || new Map();
        this.enabled = true;
        this.mobileCommands = null;
        this.addDefaultCommands();
    }

    doCommand(str) {
        if (!this.enabled) {
            this.context.print(`You can't seem to do anything at the moment.`);
            return;
        }
        const room = this.context.getRoom(this.context.player.currentRoom);
        const split = str.split(" ");
        const command = this.commands.get(split[0]);
        if (command) {
            if (command.execute) {
                // New Command object
                command.execute(split, this.context);
            } else {
                // Old function-based command
                command(split, this.context);
            }
            return;
        }
        
        // Try to match direction (handles both short and full forms)
        const direction = this.matchDirection(split[0]);
        const actualDirection = direction || split[0]; // Use the input if no mapping found

        if (room.getExit(actualDirection)) {
            this.context.move(room.getExit(actualDirection));
        }
    }

    addCommand(name, func) {
        if (Array.isArray(name)) {
            name.forEach((command) => this.commands.set(command, func));
        } else {
            this.commands.set(name, func);
        }
    }

    addCommandObject(commandObj) {
        // Add the main command name
        this.commands.set(commandObj.name, commandObj);
        // Add all aliases
        commandObj.aliases.forEach(alias => {
            this.commands.set(alias, commandObj);
        });
    }

    addCommands(commands) {
        commands.forEach((command) => {
            if (command.execute && command.getAllNames) {
                // New Command object
                this.addCommandObject(command);
            } else if (Array.isArray(command)) {
                // Old array format
                this.addCommand(command[0], command[1]);
            } else {
                // Old single command
                this.addCommand(command.name, command);
            }
        });
    }

    addDefaultCommands() {
        this.addCommands(defaultCommands);
    }

    setMobileCommands(mobileCommands) {
        this.mobileCommands = mobileCommands;
    }

    refreshMobileCommands() {
        if (this.mobileCommands) {
            this.mobileCommands.refreshCommands();
        }
    }

    matchDirection(str) {
        for (let dir of directionMap) {
            if (dir[0] == str) return dir[1]; // short form -> long form
            if (dir[1] == str) return dir[1]; // long form -> long form
        }
        return null;
    }
}