package land.chipmunk.chipmunkmod.commands;

import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.modules.CommandCore;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentSerialization;
import java.util.concurrent.CompletableFuture;

import static com.mojang.brigadier.arguments.BoolArgumentType.bool;
import static com.mojang.brigadier.arguments.BoolArgumentType.getBool;
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 CoreCommand {
    public static void register (final CommandDispatcher<FabricClientCommandSource> dispatcher) {
        dispatcher.register(
                literal("core")
                        .then(
                                literal("run")
                                        .then(
                                                argument("command", greedyString())
                                                        .executes(CoreCommand::run)
                                        )
                        )

                        .then(
                                literal("runTracked")
                                        .then(
                                                argument("command", greedyString())
                                                        .executes(CoreCommand::runTracked)
                                        )
                        )

                        .then(literal("refill").executes(CoreCommand::refill))
                        .then(literal("move").executes(CoreCommand::move))

                        .then(
                                literal("runFillCommand")
                                        .then(
                                                argument("enabled", bool())
                                                        .executes(CoreCommand::runFillCommand)
                                        )
                        )
        );
    }

    public static int run (final CommandContext<FabricClientCommandSource> context) {
        CommandCore.INSTANCE.run(getString(context, "command"));

        return Command.SINGLE_SUCCESS;
    }

    public static int runTracked (final CommandContext<FabricClientCommandSource> context) {
        final FabricClientCommandSource source = context.getSource();

        final String command = getString(context, "command");

        final CompletableFuture<CompoundTag> future = CommandCore.INSTANCE.runTracked(command);
        future.thenApply(tag -> {
            if (tag == null) return null;

            try {
                tag.read("LastOutput", ComponentSerialization.CODEC).ifPresent(source::sendFeedback);
            } catch (final Throwable throwable) {
                ChipmunkMod.LOGGER.error("Failed to read LastOutput", throwable);
            }

            return tag;
        });

        return Command.SINGLE_SUCCESS;
    }

    public static int refill (final CommandContext<FabricClientCommandSource> context) {
        CommandCore.INSTANCE.refill();

        return Command.SINGLE_SUCCESS;
    }

    public static int move (final CommandContext<FabricClientCommandSource> context) {
        final FabricClientCommandSource source = context.getSource();

        final LocalPlayer player = source.getClient().player;
        if (player != null) CommandCore.INSTANCE.move(player.getEyePosition());

        return Command.SINGLE_SUCCESS;
    }

    public static int runFillCommand (final CommandContext<FabricClientCommandSource> context) {
        final FabricClientCommandSource source = context.getSource();

        final boolean bool = getBool(context, "enabled");

        CommandCore.INSTANCE.runFillCommand = bool;

        source.sendFeedback(Component.literal("Running fill commands is now " + (bool ? "enabled" : "disabled")));

        return Command.SINGLE_SUCCESS;
    }
}
