package me.km.snuviscript.commands;

import java.util.List;
import me.hammerle.snuviscript.code.ScriptManager;
import me.hammerle.snuviscript.code.SnuviUtils;
import me.km.utils.ItemStackUtils;
import me.km.utils.Location;
import me.km.utils.Mapper;
import net.minecraft.block.Block;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.PotionUtils;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.Tag;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.World;

public class ItemCommands {
    public static void registerFunctions(ScriptManager sm) {
        sm.registerConsumer("item.drop", (sc, in) -> {
            Location l = (Location) in[0].get(sc);
            World w = l.getWorld().getWorld();
            BlockPos pos = l.getBlockPos();
            ItemStack stack = ((ItemStack) in[1].get(sc)).copy();
            int amount = stack.getCount();
            while(amount > stack.getMaxStackSize()) {
                stack.setCount(stack.getMaxStackSize());
                amount -= stack.getMaxStackSize();
                Block.spawnAsEntity(w, pos, stack.copy());
            }
            if(amount > 0) {
                stack.setCount(amount);
                Block.spawnAsEntity(w, pos, stack);
            }
        });
        sm.registerFunction("item.gettag", (sc, in) -> ItemTags.getCollection().get(new ResourceLocation(in[0].getString(sc))));
        sm.registerFunction("item.hastag", (sc, in) -> ((Tag<Item>) in[0].get(sc)).contains(((ItemStack) in[1].get(sc)).getItem()));
        sm.registerFunction("item.get", (sc, in) -> ((ItemStack) in[0].get(sc)).getItem());
        sm.registerFunction("item.gettype", (sc, in) -> ((ItemStack) in[0].get(sc)).getItem().getRegistryName().toString());
        sm.registerFunction("item.getmaxamount", (sc, in) -> (double) ((ItemStack) in[0].get(sc)).getMaxStackSize());
        sm.registerFunction("item.getamount", (sc, in) -> (double) ((ItemStack) in[0].get(sc)).getCount());
        sm.registerConsumer("item.setamount", (sc, in) -> ((ItemStack) in[0].get(sc)).setCount(in[1].getInt(sc)));
        sm.registerFunction("item.getfulltext", (sc, in) -> ((ItemStack) in[0].get(sc)).getTextComponent());
        sm.registerFunction("item.hasname", (sc, in) -> ((ItemStack) in[0].get(sc)).hasDisplayName());
        sm.registerFunction("item.getname", (sc, in) -> ((ItemStack) in[0].get(sc)).getDisplayName().getFormattedText());
        sm.registerConsumer("item.setname", (sc, in) -> {
            ((ItemStack) in[0].get(sc)).setDisplayName(new StringTextComponent(SnuviUtils.connect(sc, in, 1)));
        });
        sm.registerFunction("item.getlore", (sc, in) -> ItemStackUtils.getLore((ItemStack) in[0].get(sc)));
        sm.registerConsumer("item.setlore", (sc, in) -> {
            ItemStackUtils.setLore((ItemStack) in[0].get(sc), (List<Object>) in[1].get(sc));
        });
        sm.registerConsumer("item.addlore", (sc, in) -> {
            ItemStackUtils.addLore((ItemStack) in[0].get(sc), SnuviUtils.connect(sc, in, 2), in[1].getInt(sc));
        });
        sm.registerConsumer("item.setcooldown", (sc, in) -> {
            ((PlayerEntity) in[0].get(sc)).getCooldownTracker().setCooldown(((ItemStack) in[1].get(sc)).getItem(), in[2].getInt(sc));
        });
        sm.registerConsumer("item.addpotion", (sc, in) -> {
            ItemStack stack = (ItemStack) in[0].get(sc);
            List<EffectInstance> list = PotionUtils.getEffectsFromStack(stack);
            list.add(new EffectInstance(Mapper.getPotion(in[1].getString(sc)), in[2].getInt(sc), in[3].getInt(sc)));
            PotionUtils.appendEffects(stack, list);
        });
        sm.registerConsumer("item.addflag", (sc, in) -> {
            ItemStackUtils.addItemFlag((ItemStack) in[0].get(sc), ItemStackUtils.ItemFlag.valueOf(in[1].getString(sc).toUpperCase()));
        });
        sm.registerConsumer("item.addattribute", (sc, in) -> {
            ItemStackUtils.addAttribute((ItemStack) in[0].get(sc),
                    ItemStackUtils.Attribute.valueOf(in[1].getString(sc).toUpperCase()),
                    EquipmentSlotType.valueOf(in[2].getString(sc).toUpperCase()),
                    in[3].getDouble(sc),
                    AttributeModifier.Operation.valueOf(in[4].getString(sc).toUpperCase()));
        });
        sm.registerConsumer("item.setmagic", (sc, in) -> {
            ItemStack stack = (ItemStack) in[0].get(sc);
            int value = in[1].getInt(sc);
            if(stack.getItem() instanceof ArmorItem) {
                CompoundNBT com = stack.getTag();
                if(com == null) {
                    com = new CompoundNBT();
                    stack.setTag(com);
                }
                com.putInt("magic", value);
            } else {
                throw new IllegalArgumentException("magic resistance is only for armor");
            }
        });
        sm.registerFunction("item.clone", (sc, in) -> ((ItemStack) in[0].get(sc)).copy());
        sm.registerFunction("item.getmaxdamage", (sc, in) -> (double) ((ItemStack) in[0].get(sc)).getMaxDamage());
        sm.registerFunction("item.isdamageable", (sc, in) -> ((ItemStack) in[0].get(sc)).isDamageable());
        sm.registerFunction("item.getdamage", (sc, in) -> (double) ((ItemStack) in[0].get(sc)).getDamage());
        sm.registerConsumer("item.setdamage", (sc, in) -> {
            ((ItemStack) in[0].get(sc)).setDamage(in[1].getInt(sc));
        });
    }
}
