package com.r3944realms.leashedplayer.content.commands;

import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry;
import com.r3944realms.leashedplayer.content.gamerules.Server.CanCommonPlayerChangeSelfTalkArea;
import com.r3944realms.leashedplayer.modInterface.ServerPlayerCapacity;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.arguments.EntityArgument;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static com.r3944realms.leashedplayer.content.commands.Command.SHOULD_USE_PREFIX;
import static com.r3944realms.leashedplayer.content.commands.Command.getLiterArgumentBuilderOfCSS;


public class ChatCommand {
    private static final String LP_CHAT_MESSAGE_ = "leashedplayer.command.chat.message.";
    public static final String NO_RIGHT = LP_CHAT_MESSAGE_ + "no_right";
    public static final String SELF_TALK_AREA_SET = LP_CHAT_MESSAGE_ + "talkarea.self.set",
                            SELF_TALK_AREA_PREFERENCE_SET = LP_CHAT_MESSAGE_ + "talkarea.self.preference.set",
                            SELF_TALK_AREA_PREFERENCE_NOT_SET = LP_CHAT_MESSAGE_ + "talkarea.self.preference_not_set",
                            SELF_TALK_AREA_UNLIMITED = LP_CHAT_MESSAGE_ + "talkarea.self.unlimited",
                            SELF_TALK_AREA_CURRENT_CONFIG = LP_CHAT_MESSAGE_ + "talkarea.self.current_config",
                            TALK_AREA_SET = LP_CHAT_MESSAGE_ + "talkarea.set",
                            TALK_AREA_PREFERENCE_SET = LP_CHAT_MESSAGE_ + "talkarea.preference.set",
                            TALK_AREA_PREFERENCE_NOT_SET = LP_CHAT_MESSAGE_ + "talkarea.preference_not_set",
                            TALK_AREA_UNLIMITED = LP_CHAT_MESSAGE_ + "talkarea.unlimited",
                            TALK_AREA_CURRENT_CONFIG = LP_CHAT_MESSAGE_ + "talkarea.current_config";
    public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
        @Nullable List<LiteralArgumentBuilder<CommandSourceStack>> nodeList = SHOULD_USE_PREFIX ? null : new ArrayList<>();
        LiteralArgumentBuilder<CommandSourceStack> literalArgumentBuilder = Commands.literal(com.r3944realms.leashedplayer.content.commands.Command.PREFIX);
        LiteralArgumentBuilder<CommandSourceStack> $$leashRoot = getLiterArgumentBuilderOfCSS("talkArea", !SHOULD_USE_PREFIX, nodeList);
        Command<CommandSourceStack> chat$self$talkArea_set = (context -> {
            CommandSourceStack source = context.getSource();
            ServerPlayer player = source.getPlayerOrException();
            ServerPlayerCapacity serverPlayer = (ServerPlayerCapacity) player;
            if((!player.hasPermissions(2) && !GameruleRegistry.getGameruleBoolValue(source.getLevel(), CanCommonPlayerChangeSelfTalkArea.ID))) {
                source.sendFailure(Component.translatable(NO_RIGHT));
                return 1;
            }
            int integer = IntegerArgumentType.getInteger(context, "talkAreaRadius");
            serverPlayer.setTalkArea(integer);
            source.sendSuccess(() -> Component.translatable(SELF_TALK_AREA_SET, integer),true);
            return 0;
        });
        Command<CommandSourceStack> chat$self$talkArea_preference_set = (context -> {
            CommandSourceStack source = context.getSource();
            ServerPlayer player = source.getPlayerOrException();
            ServerPlayerCapacity serverPlayer = (ServerPlayerCapacity) player;
            if((!player.hasPermissions(2) && !GameruleRegistry.getGameruleBoolValue(source.getLevel(), CanCommonPlayerChangeSelfTalkArea.ID))) {
                source.sendFailure(Component.translatable(NO_RIGHT));
                return 1;
            }
            int integer = IntegerArgumentType.getInteger(context, "talkAreaPreferenceRadius");
            serverPlayer.setTalkAreaPreference(integer);
            source.sendSuccess(() -> Component.translatable(SELF_TALK_AREA_PREFERENCE_SET, integer),true);
            return 0;
        });
        Command<CommandSourceStack> chat$self$talkArea_usePreference = (context -> {
            CommandSourceStack source = context.getSource();
            ServerPlayer player = source.getPlayerOrException();
            ServerPlayerCapacity serverPlayer = (ServerPlayerCapacity) player;
            if((!player.hasPermissions(2) && !GameruleRegistry.getGameruleBoolValue(source.getLevel(), CanCommonPlayerChangeSelfTalkArea.ID))) {
                source.sendFailure(Component.translatable(NO_RIGHT));
                return 1;
            }
            if(serverPlayer.getTalkAreaPreference() == -1) {
                source.sendFailure(Component.translatable(SELF_TALK_AREA_PREFERENCE_NOT_SET));
                return 1;
            }
            int currentPreference = serverPlayer.getTalkAreaPreference();
            serverPlayer.setTalkArea(currentPreference);
            source.sendSuccess(() -> Component.translatable(SELF_TALK_AREA_PREFERENCE_SET, currentPreference),true);
            return 0;
        });
        Command<CommandSourceStack> chat$self$talkArea_unlimited = (context -> {
            CommandSourceStack source = context.getSource();
            ServerPlayer player = source.getPlayerOrException();
            if((!player.hasPermissions(2) && !GameruleRegistry.getGameruleBoolValue(source.getLevel(), CanCommonPlayerChangeSelfTalkArea.ID))) {
                source.sendFailure(Component.translatable(NO_RIGHT));
                return 1;
            }
            source.sendSuccess(() -> Component.translatable(SELF_TALK_AREA_UNLIMITED),true);
            return 0;
        });
        Command<CommandSourceStack> chat$self$talkArea_getCurrentConfig = (context -> {
            CommandSourceStack source = context.getSource();
            ServerPlayerCapacity serverPlayer = (ServerPlayerCapacity) source.getPlayerOrException();
            source.sendSuccess(() -> Component.translatable(SELF_TALK_AREA_CURRENT_CONFIG,serverPlayer.getTalkArea(),serverPlayer.getTalkAreaPreference()),true);
            return 0;
        });
        Command<CommandSourceStack> chat$talkArea_set = (context -> {
            CommandSourceStack source = context.getSource();
            Collection<ServerPlayer> players = EntityArgument.getPlayers(context, "players");
            int integer = IntegerArgumentType.getInteger(context, "talkAreaRadius");
            players.forEach(i-> {
                ((ServerPlayerCapacity)i).setTalkArea(integer);
                source.sendSuccess(() -> Component.translatable(TALK_AREA_SET, i.getName().copy().withStyle(), integer),true);
            });

            return 0;
        });
        Command<CommandSourceStack> chat$talkArea_preference_set = (context -> {
            CommandSourceStack source = context.getSource();
            Collection<ServerPlayer> players = EntityArgument.getPlayers(context, "players");
            int integer = IntegerArgumentType.getInteger(context, "talkAreaPreferenceRadius");
            players.forEach(i-> {
                ((ServerPlayerCapacity)i).setTalkAreaPreference(integer);
                source.sendSuccess(() -> Component.translatable(TALK_AREA_PREFERENCE_SET, i.getName().copy().withStyle(), integer),true);
            });
            return 0;
        });
        Command<CommandSourceStack> chat$talkArea_usePreference = (context -> {
            CommandSourceStack source = context.getSource();
            Collection<ServerPlayer> players = EntityArgument.getPlayers(context, "players");
            players.forEach(i-> {
                int talkAreaPreference = ((ServerPlayerCapacity)i).getTalkAreaPreference();
                if(talkAreaPreference == -1) {
                    source.sendFailure(Component.translatable(TALK_AREA_PREFERENCE_NOT_SET,i.getName().copy().withStyle()));
                } else {
                    ((ServerPlayerCapacity) i).setTalkArea(talkAreaPreference);
                    source.sendSuccess(() -> Component.translatable(TALK_AREA_PREFERENCE_SET, i.getName().copy().withStyle(), talkAreaPreference),true);
                }
            });
            return 0;
        });
        Command<CommandSourceStack> chat$talkArea_unlimited = (context -> {
            CommandSourceStack source = context.getSource();
            Collection<ServerPlayer> players = EntityArgument.getPlayers(context, "players");
            players.forEach(i-> {
                ((ServerPlayerCapacity)i).setTalkArea(-1);
                source.sendSuccess(() -> Component.translatable(TALK_AREA_UNLIMITED, i.getName().copy().withStyle()),true);
            });
            return 0;
        });
        Command<CommandSourceStack> chat$talkArea_getCurrentConfig = (context -> {
            CommandSourceStack source = context.getSource();
            Collection<ServerPlayer> players = EntityArgument.getPlayers(context, "players");
            players.forEach(i-> source.sendSuccess(() -> Component.translatable(TALK_AREA_CURRENT_CONFIG, i.getName().copy().withStyle(),((ServerPlayerCapacity)i).getTalkArea(),((ServerPlayerCapacity)i).getTalkAreaPreference()), true));
            return 0;
        });
        LiteralArgumentBuilder<CommandSourceStack> selfTalkAreaSet = $$leashRoot.then(Commands.literal("set")
                        .then(Commands.argument("talkAreaRadius", IntegerArgumentType.integer(0))
                                .executes(chat$self$talkArea_set)))
                .then(Commands.literal("setPreference")
                        .then(Commands.argument("talkAreaPreferenceRadius", IntegerArgumentType.integer(0))
                                .executes(chat$self$talkArea_preference_set)))
                .then(Commands.literal("usePreference")
                        .executes(chat$self$talkArea_usePreference))
                .then(Commands.literal("unlimited")
                        .executes(chat$self$talkArea_unlimited))
                .then(Commands.literal("currentConfig")
                        .executes(chat$self$talkArea_getCurrentConfig));
        LiteralArgumentBuilder<CommandSourceStack> TalkAreaCommon = $$leashRoot.then(Commands.argument("players", EntityArgument.players()).requires(cs -> cs.hasPermission(2))
                .then(Commands.literal("set")
                        .then(Commands.argument("talkAreaRadius", IntegerArgumentType.integer(0))
                                .executes(chat$talkArea_set)))
                .then(Commands.literal("setPreference")
                        .then(Commands.argument("talkAreaPreferenceRadius", IntegerArgumentType.integer(0))
                                .executes(chat$talkArea_preference_set)))
                .then(Commands.literal("usePreference")
                        .executes(chat$talkArea_usePreference))
                .then(Commands.literal("unlimited")
                        .executes(chat$talkArea_unlimited))
                .then(Commands.literal("currentConfig")
                        .executes(chat$talkArea_getCurrentConfig)));
        if(SHOULD_USE_PREFIX) {
            literalArgumentBuilder.then(selfTalkAreaSet);
            literalArgumentBuilder.then(TalkAreaCommon);
            dispatcher.register(literalArgumentBuilder);
        } else {
            nodeList.forEach(dispatcher::register);
        }
    }
}
