package land.chipmunk.chipmunkmod.command;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import land.chipmunk.chipmunkmod.commands.*;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.MinecraftClient;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.text.ClickEvent;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.text.Texts;
import net.minecraft.util.Formatting;

public class CommandManager {
    public static CommandManager INSTANCE;
    public CommandDispatcher<FabricClientCommandSource> dispatcher = new CommandDispatcher<>();
    public String prefix;

    public CommandManager (final String prefix, final CommandRegistryAccess commandRegistryAccess) {
        this.prefix = prefix;

        TestCommand.register(this.dispatcher);
        CoreCommand.register(this.dispatcher);
        UsernameCommand.register(this.dispatcher);
        CloopCommand.register(this.dispatcher);
        ValidateCommand.register(this.dispatcher);
        ItemCommand.register(this.dispatcher, commandRegistryAccess);
        CustomChatCommand.register(this.dispatcher);
        EvalCommand.register(this.dispatcher);
        MusicCommand.register(this.dispatcher);
        RainbowNameCommand.register(this.dispatcher);
        SayCommand.register(this.dispatcher);
        AutoSkinCommand.register(this.dispatcher);
        ReloadConfigCommand.register(this.dispatcher);
        SelfCareCommand.register(this.dispatcher);
    }

    public static LiteralArgumentBuilder<FabricClientCommandSource> literal (final String name) {
        return LiteralArgumentBuilder.literal(name);
    }

    public static <T> RequiredArgumentBuilder<FabricClientCommandSource, T> argument (final String name, final ArgumentType<T> type) {
        return RequiredArgumentBuilder.argument(name, type);
    }

    public void executeCommand (final String command) {
        final MinecraftClient client = MinecraftClient.getInstance();

        final FabricClientCommandSource commandSource = (FabricClientCommandSource) client.getNetworkHandler().getCommandSource();

        try {
            dispatcher.execute(command, commandSource);
        } catch (final CommandSyntaxException e) {
            commandSource.sendError(Texts.toText(e.getRawMessage()));
            final Text context = getContext(e);
            if (context != null) commandSource.sendError(context);
        } catch (final Exception e) {
            commandSource.sendError(Text.of(e.getMessage()));
        }
    }

    public Text getContext (final CommandSyntaxException exception) {
        final int _cursor = exception.getCursor();
        final String input = exception.getInput();

        if (input == null || _cursor < 0) {
            return null;
        }
        final MutableText text = Text.literal("")
                .formatted(Formatting.GRAY);
        text.setStyle(text.getStyle().withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, prefix + input)));

        final int cursor = Math.min(input.length(), _cursor);

        if (cursor > CommandSyntaxException.CONTEXT_AMOUNT) {
            text.append(Text.literal("..."));
        }

        text
                .append(Text.literal(input.substring(Math.max(0, cursor - CommandSyntaxException.CONTEXT_AMOUNT), cursor)))
                .append(Text.literal(input.substring(cursor)).formatted(Formatting.RED, Formatting.UNDERLINE))
                .append(Text.translatable("command.context.here").formatted(Formatting.RED, Formatting.ITALIC));

        return text;
    }
}
