package com.tiedup.remake.commands.subcommands;

import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.network.sync.PacketSyncBindState;
import com.tiedup.remake.v2.bondage.CollarHelper;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.tiedup.remake.commands.CommandHelper;
import com.tiedup.remake.core.SystemMessageManager;
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem;
import net.minecraft.ChatFormatting;
import net.minecraft.resources.ResourceLocation;
import com.tiedup.remake.state.PlayerBindState;
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 net.minecraft.world.item.ItemStack;

@SuppressWarnings("null")
public class CollarCommands {

    public static void register(LiteralArgumentBuilder<CommandSourceStack> root) {
        // /tiedup collar <player>
        root.then(
            Commands.literal("collar")
                .requires(CommandHelper.REQUIRES_OP)
                .then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(CollarCommands::collar)
                )
        );
        // /tiedup takecollar <player>
        root.then(
            Commands.literal("takecollar")
                .requires(CommandHelper.REQUIRES_OP)
                .then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(CollarCommands::takecollar)
                )
        );
        // /tiedup enslave <player>
        root.then(
            Commands.literal("enslave")
                .requires(CommandHelper.REQUIRES_OP)
                .then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(CollarCommands::enslave)
                )
        );
        // /tiedup free <player>
        root.then(
            Commands.literal("free")
                .requires(CommandHelper.REQUIRES_OP)
                .then(
                    Commands.argument(
                        "player",
                        EntityArgument.player()
                    ).executes(CollarCommands::free)
                )
        );
    }

    static int collar(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        ServerPlayer targetPlayer = EntityArgument.getPlayer(context, "player");
        PlayerBindState state = PlayerBindState.getInstance(targetPlayer);

        if (state == null) {
            context
                .getSource()
                .sendFailure(Component.translatable("command.tiedup.error.no_state"));
            return 0;
        }

        if (state.hasCollar()) {
            context
                .getSource()
                .sendFailure(
                    Component.translatable(
                        "command.tiedup.collar.already_collared",
                        targetPlayer.getName().getString()
                    )
                );
            return 0;
        }

        ItemStack collar = com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem.createStack(net.minecraft.resources.ResourceLocation.fromNamespaceAndPath("tiedup", "classic_collar"));

        if (context.getSource().getEntity() instanceof ServerPlayer executor) {
            CollarHelper.addOwner(collar, executor);
        }

        state.putCollarOn(collar);

        CommandHelper.syncPlayerState(targetPlayer, state);

        context
            .getSource()
            .sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.collar.collared",
                        targetPlayer.getName().getString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
        SystemMessageManager.sendToTarget(
            context.getSource().getEntity(),
            targetPlayer,
            SystemMessageManager.MessageCategory.COLLARED
        );

        return 1;
    }

    static int takecollar(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        ServerPlayer targetPlayer = EntityArgument.getPlayer(context, "player");
        PlayerBindState state = PlayerBindState.getInstance(targetPlayer);

        if (state == null) {
            context
                .getSource()
                .sendFailure(Component.translatable("command.tiedup.error.no_state"));
            return 0;
        }

        if (!state.hasCollar()) {
            context
                .getSource()
                .sendFailure(
                    Component.translatable(
                        "command.tiedup.collar.no_collar",
                        targetPlayer.getName().getString()
                    )
                );
            return 0;
        }

        state.takeCollarOff();
        CommandHelper.syncPlayerState(targetPlayer, state);

        context
            .getSource()
            .sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.collar.removed",
                        targetPlayer.getName().getString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
        SystemMessageManager.sendToTarget(
            context.getSource().getEntity(),
            targetPlayer,
            SystemMessageManager.MessageCategory.UNCOLLARED
        );

        return 1;
    }

    static int enslave(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        ServerPlayer targetPlayer = EntityArgument.getPlayer(context, "player");
        PlayerBindState state = PlayerBindState.getInstance(targetPlayer);

        if (state == null) {
            context
                .getSource()
                .sendFailure(Component.translatable("command.tiedup.error.no_state"));
            return 0;
        }

        // First fully restrain
        if (!state.isTiedUp()) {
            ItemStack ropes = DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "ropes"));
            state.putBindOn(ropes);
        }
        if (!state.isGagged()) {
            ItemStack gag = DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "cloth_gag"));
            state.putGagOn(gag);
        }
        if (!state.isBlindfolded()) {
            ItemStack blindfold = DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "classic_blindfold"));
            state.putBlindfoldOn(blindfold);
        }
        if (!state.hasCollar()) {
            ItemStack collar = com.tiedup.remake.v2.bondage.datadriven.DataDrivenBondageItem.createStack(net.minecraft.resources.ResourceLocation.fromNamespaceAndPath("tiedup", "classic_collar"));
            if (
                context.getSource().getEntity() instanceof ServerPlayer executor
            ) {
                CollarHelper.addOwner(collar, executor);
            }
            state.putCollarOn(collar);
        }
        if (!state.hasEarplugs()) {
            ItemStack earplugs = DataDrivenBondageItem.createStack(ResourceLocation.fromNamespaceAndPath("tiedup", "classic_earplugs"));
            state.putEarplugsOn(earplugs);
        }

        // Capture target (this makes them a captive)
        if (context.getSource().getEntity() instanceof ServerPlayer master) {
            PlayerBindState masterState = PlayerBindState.getInstance(master);
            if (masterState != null && masterState.getCaptorManager() != null) {
                masterState.getCaptorManager().addCaptive(state);
            }
        }

        CommandHelper.syncPlayerState(targetPlayer, state);

        context
            .getSource()
            .sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.collar.enslaved",
                        targetPlayer.getName().getString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
        SystemMessageManager.sendEnslaved(
            context.getSource().getEntity(),
            targetPlayer
        );

        return 1;
    }

    static int free(CommandContext<CommandSourceStack> context)
        throws CommandSyntaxException {
        ServerPlayer targetPlayer = EntityArgument.getPlayer(context, "player");
        PlayerBindState state = PlayerBindState.getInstance(targetPlayer);

        if (state == null) {
            context
                .getSource()
                .sendFailure(Component.translatable("command.tiedup.error.no_state"));
            return 0;
        }

        if (!state.isCaptive()) {
            context
                .getSource()
                .sendFailure(
                    Component.translatable(
                        "command.tiedup.collar.not_captured",
                        targetPlayer.getName().getString()
                    )
                );
            return 0;
        }

        state.free(true);

        PacketSyncBindState statePacket = PacketSyncBindState.fromPlayer(
            targetPlayer
        );
        if (statePacket != null) {
            ModNetwork.sendToPlayer(statePacket, targetPlayer);
        }

        context
            .getSource()
            .sendSuccess(
                () ->
                    Component.translatable(
                        "command.tiedup.collar.freed",
                        targetPlayer.getName().getString()
                    ).withStyle(ChatFormatting.GREEN),
                true
            );
        SystemMessageManager.sendFreed(targetPlayer);

        return 1;
    }

}
