/*
 * Original project: RedEnvelope by KaguyaStudio-MC
 * Original project link: https://github.com/KaguyaStudio-MC/RedEnvelope
 * Modified by: LeisureTimeDock
 * This file is part of RedEnvelope
 * Licensed under Camellia License Version 1.0
 */

package top.leisuretimedock.redenvelope.core.command;

import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import top.leisuretimedock.redenvelope.RedEnvelope;
import top.leisuretimedock.redenvelope.core.network.OpenRedEnvelopePacket;
import top.leisuretimedock.redenvelope.core.network.RedEnvelopePacket;
import top.leisuretimedock.redenvelope.core.util.REUtil;
import top.leisuretimedock.redenvelope.core.capability.RECapability;

import java.util.Optional;
import java.util.UUID;

public class CommandExecutes {

    public static int sendLuckWithItemCount(CommandContext<CommandSourceStack> context) {
        int itemcount = IntegerArgumentType.getInteger(context, "itemcount");
        return sendLuck(context,itemcount);
    }
    public static int sendLuckWithoutItemCount(CommandContext<CommandSourceStack> context) {
        return sendLuck(context,-1);
    }
    public static int sendLuck(CommandContext<CommandSourceStack> context,int itemcount) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        ItemStack mainHandItem = player.getMainHandItem();
        if (mainHandItem.isEmpty()) {
            player.displayClientMessage(Component.translatable("chat.red_envelope.require_holding_item"), true);
            REUtil.playSoundForPlayer(player, SoundEvents.VILLAGER_NO);
            return 0;
        }
        int count = IntegerArgumentType.getInteger(context, "count");
        if (!player.isCreative() && mainHandItem.getCount()< itemcount && itemcount!=-1) return 0;
        ItemStack copy = mainHandItem.copy();
        if(itemcount != -1)
            copy.setCount(itemcount);
        else
            itemcount = copy.getCount();

        @NotNull Optional<RedEnvelopePacket> luck = REUtil.create(player, copy, REUtil.LUCK, count);
        int finalItemcount = itemcount;
        luck.ifPresent(packet -> {
            RedEnvelope.LOGGER.debug("send luck packet");
            RedEnvelopePacket._handleServer(packet, player);
            if (!player.isCreative()) {
                mainHandItem.shrink(finalItemcount);
            }
        });
        return 1;
    }

    public static int sendSpellWithItemCount(CommandContext<CommandSourceStack> context) {
        int itemcount = IntegerArgumentType.getInteger(context, "itemcount");
        return sendSpell(context,itemcount);
    }
    public static int sendSpellWithoutItemCount(CommandContext<CommandSourceStack> context) {
        return sendSpell(context,-1);
    }
    public static int sendSpell(CommandContext<CommandSourceStack> context,int itemcount) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        ItemStack mainHandItem = player.getMainHandItem();
        if (mainHandItem.isEmpty()) {
            player.displayClientMessage(Component.translatable("chat.red_envelope.require_holding_item"), true);
            REUtil.playSoundForPlayer(player, SoundEvents.VILLAGER_NO);
            return 0;
        }
        int count = IntegerArgumentType.getInteger(context, "count");
        String words = StringArgumentType.getString(context, "words");
        if (words.isEmpty() || words.length() > 128) {
            player.displayClientMessage(Component.translatable("chat.red_envelope.spell_word_length"), true);
            REUtil.playSoundForPlayer(player, SoundEvents.VILLAGER_NO);
            return 0;
        }
        if (player.isCreative()) {
            ItemStack copy = mainHandItem.copy();
            REUtil.create(player, copy, REUtil.SPELL, count).ifPresent(
                   packet -> {
                       packet.extraData().putString("spell", words);
                       RedEnvelope.LOGGER.debug("creative player send spell packet");
                       RedEnvelopePacket._handleServer(packet, player);
                   }
           );
        } else {
            if(mainHandItem.getCount() < itemcount && itemcount != -1) return 0;
            ItemStack copy = mainHandItem.copy();
            if(itemcount != -1)
                copy.setCount(itemcount);
            else
                itemcount = copy.getCount();

            int finalItemcount = itemcount;
            REUtil.create(player, copy, REUtil.SPELL, count).ifPresent(
                    packet -> {
                        packet.extraData().putString("spell", words);
                        RedEnvelope.LOGGER.debug("send spell packet");
                        RedEnvelopePacket._handleServer(packet,player);
                        mainHandItem.shrink(finalItemcount);
                    }
            );
        }
        return 1;
    }

    public static int sendCommon(CommandContext<CommandSourceStack> context) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        ItemStack mainHandItem = player.getMainHandItem();
        if (mainHandItem.isEmpty()) {
            player.displayClientMessage(Component.translatable("chat.red_envelope.require_holding_item"), true);
            REUtil.playSoundForPlayer(player, SoundEvents.VILLAGER_NO);
            return 0;
        }
        int count = IntegerArgumentType.getInteger(context, "count");
        int single = IntegerArgumentType.getInteger(context, "single");
        if (!player.isCreative() && mainHandItem.getCount()< single*count) {
            player.sendSystemMessage(Component.translatable("chat.red_envelope.notenough"));
            return 0;
        }
        ItemStack copy = mainHandItem.copy();
        copy.setCount(count);
        REUtil.create(player, copy, REUtil.COMMON, count).ifPresent(
                packet -> {
                    packet.extraData().putInt("single",single);
                    RedEnvelope.LOGGER.debug("send common packet");
                    RedEnvelopePacket._handleServer(packet,player);
                    if (!player.isCreative()) {
                        mainHandItem.shrink(single * count);
                    }
                }
        );
        return 1;
    }

    public static int open(CommandContext<CommandSourceStack> context) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        String uuid = StringArgumentType.getString(context, "uuid");
        OpenRedEnvelopePacket._handleServer(new OpenRedEnvelopePacket(UUID.fromString(uuid)),player);
        return 1;
    }

    public static int withdraw(CommandContext<CommandSourceStack> context) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        String uuid = StringArgumentType.getString(context, "uuid");
        var copy = player.getCapability(RECapability.HONGBAO_STORAGE);
        copy.ifPresent(i -> {
                    RedEnvelopePacket packet = i.get(UUID.fromString(uuid));
                    if (packet != null) {
                        REUtil.withdraw(player.server, packet, REUtil.WITHDRAW);
                    }
                }
        );
        return 1;
    }

    public static int queryWithUUID(CommandContext<CommandSourceStack> context) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        String uuid = StringArgumentType.getString(context, "uuid");
        REUtil.query(player,UUID.fromString(uuid));
        return 1;
    }

    public static int query(CommandContext<CommandSourceStack> context) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        REUtil.query(player);
        return 1;
    }

    public static int queryRemain(CommandContext<CommandSourceStack> context) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        REUtil.queryRemain(player);
        return 1;
    }

    public static int queryCooldownSpell(CommandContext<CommandSourceStack> context) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        REUtil.queryCooldown(player, REUtil.SPELL);
        return 1;
    }

    public static int queryCooldownCommon(CommandContext<CommandSourceStack> context) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        REUtil.queryCooldown(player, REUtil.COMMON);
        return 1;
    }

    public static int queryCooldownLuck(CommandContext<CommandSourceStack> context) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        REUtil.queryCooldown(player, REUtil.LUCK);
        return 1;
    }

    public static int queryCooldown(CommandContext<CommandSourceStack> context) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        REUtil.queryCooldown(player, null);
        return 1;
    }

    public static int queryList(CommandContext<CommandSourceStack> context) {
        ServerPlayer player = context.getSource().getPlayer();
        if(player == null) return 0;
        REUtil.queryList(player);
        return 1;
    }

}
