package land.chipmunk.chipmunkmod.commands;

import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import land.chipmunk.chipmunkmod.modules.CommandLoopManager;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.network.chat.Component;

import java.util.List;

import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.arguments.LongArgumentType.getLong;
import static com.mojang.brigadier.arguments.LongArgumentType.longArg;
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;

public class CloopCommand {
    private static final DynamicCommandExceptionType INVALID_CLOOP_ID_EXCEPTION = new DynamicCommandExceptionType(id -> Component.translatable("Invalid cloop id: %s", Component.literal(String.valueOf(id))));

    public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) {
        dispatcher.register(
                literal("cloop")
                        .then(literal("add")
                                      .then(argument("interval", longArg())
                                                    .then(argument("command", greedyString())
                                                                  .executes(CloopCommand::addCloop)
                                                    )
                                      )
                        )
                        .then(literal("remove")
                                      .then(argument("id", integer())
                                                    .executes(CloopCommand::removeCloop)))
                        .then(literal("clear").executes(CloopCommand::clearCloops))
                        .then(literal("list").executes(CloopCommand::listCloops))
        );
    }

    public static int addCloop (final CommandContext<FabricClientCommandSource> context) {
        final FabricClientCommandSource source = context.getSource();
        final long interval = getLong(context, "interval");
        final String command = getString(context, "command");

        final int id = CommandLoopManager.INSTANCE.loopCommand(command, interval);

        source.sendFeedback(Component.translatable("Successfully created a loop for command '%s' with id %s", Component.literal(command), Component.literal(String.valueOf(id))));
        return Command.SINGLE_SUCCESS;
    }

    public static int removeCloop (final CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
        final FabricClientCommandSource source = context.getSource();
        final CommandLoopManager manager = CommandLoopManager.INSTANCE;
        final int id = getInteger(context, "id");

        if (id < 0 || id >= manager.commandLoops.size()) throw INVALID_CLOOP_ID_EXCEPTION.create(id);

        manager.removeAndStop(id);

        source.sendFeedback(Component.translatable("Successfully removed loop with id %s", Component.literal(String.valueOf(id))));
        return Command.SINGLE_SUCCESS;
    }

    public static int clearCloops (final CommandContext<FabricClientCommandSource> context) {
        final FabricClientCommandSource source = context.getSource();
        final CommandLoopManager manager = CommandLoopManager.INSTANCE;

        manager.clearLoops();

        source.sendFeedback(Component.translatable("Successfully cleared all command loops"));
        return Command.SINGLE_SUCCESS;
    }

    public static int listCloops (final CommandContext<FabricClientCommandSource> context) {
        final FabricClientCommandSource source = context.getSource();
        final List<CommandLoopManager.CommandLoop> loops = CommandLoopManager.INSTANCE.commandLoops;

        int id = 0;
        for (final CommandLoopManager.CommandLoop loop : loops) {
            source.sendFeedback(Component.translatable("%s: %s (%s)", Component.literal(String.valueOf(id)), Component.literal(loop.command), Component.literal(String.valueOf(loop.interval))));
            id++;
        }

        if (id == 0) {
            source.sendFeedback(Component.translatable("No command loops are currently running"));
        }

        return Command.SINGLE_SUCCESS;
    }
}
