package com.zivilon.cinder_loe.util;

import com.zivilon.cinder_loe.CinderLoE;
import com.zivilon.cinder_loe.entity.npc.dwarf.*;
import com.zivilon.cinder_loe.mixins.MixinLOTREntityNPC;
import com.zivilon.cinder_loe.droptables.*;
import com.zivilon.cinder_loe.droptables.DropTable.*;
import com.zivilon.cinder_loe.util.IMixinEntityPlayer;

import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.init.Items;
import net.minecraft.nbt.*;
import net.minecraft.potion.Potion;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ChatComponentTranslation;

import lotr.common.LOTRMod;
import lotr.common.item.LOTRItemArmor;
import lotr.common.item.LOTRMaterial;
import lotr.common.entity.npc.*;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class PickpocketUtils {
    public static Random random = new Random();

    public static boolean can_pickpocket(EntityPlayer player, LOTREntityNPC target) {
        if (!player.isSneaking()) return false;

        DropTable table = ((ILootableEntity)(Object)target).get_drop_table();
        if (table == null)  {
            return false;
        }

        List<DropInstance> drops = table.drop_list;
        boolean has_pickpocket_drops = drops.stream().anyMatch(drop ->
            drop.conditions != null &&
            Arrays.stream(drop.conditions).anyMatch(DropContext.PICKPOCKET::equals)
        );

        if (!has_pickpocket_drops)  {
            return false;
        }

        if (((IMixinEntityPlayer)player).get_last_pickpocket_attempt() > (int)(System.currentTimeMillis() / 1000L - 1) || ((ILootableEntity)(Object)target).get_last_pickpocket() > (int)(System.currentTimeMillis() / 1000L - 4)) {
            if (random.nextInt(10000) == 1) {
                player.addChatMessage(new ChatComponentTranslation("pickpocket.cooldown_alt"));
            } else {
                player.addChatMessage(new ChatComponentTranslation("pickpocket.cooldown"));
            }
            return false;
        }

        return true;
    }
    public static boolean pickpocket(EntityPlayer player, LOTREntityNPC target) {
        ILootableEntity npc = (ILootableEntity)(Object)target;
        float penalty = 1.0F;
        if (!is_behind(player, (EntityLivingBase)target)) penalty -= 0.4F;
        if (npc.get_last_pickpocket() > (int)(System.currentTimeMillis() / 1000L - 60)) penalty -= 0.4F;
        if (is_invisible(player)) penalty += 0.4F;
        if (is_cloaked(player)) penalty += 0.2F;
        boolean success = random.nextFloat() < npc.get_pickpocket_chance() * penalty;
        return success;
    }

    public static boolean is_behind(EntityPlayer player, EntityLivingBase entity) {
        float npcYaw = entity.rotationYaw % 360;
        float playerYaw = player.rotationYaw % 360;
        float angleDiff = MathHelper.wrapAngleTo180_float(npcYaw - playerYaw);
        boolean is_behind = Math.abs(angleDiff) < 30F;
        return is_behind;
    }

    public static boolean is_invisible(EntityPlayer player) {
        boolean invisible = player.isPotionActive(Potion.invisibility);
        return (invisible && !wearing_armor(player));

    }
    public static boolean is_cloaked(EntityPlayer player) {
        ItemStack[] equipment = player.inventory.armorInventory;
        for (ItemStack armor : equipment) {
            if (armor == null) return false;
            Item item = armor.getItem();
            if (!(item instanceof LOTRItemArmor) || ((LOTRItemArmor)item).getLOTRArmorMaterial() != LOTRMaterial.HITHLAIN)
                return false;
        }
        return true;
    }
    public static boolean wearing_armor(EntityPlayer player) {
        ItemStack[] equipment = player.inventory.armorInventory;
        for (ItemStack armor : equipment) {
            if (armor != null) return true;
        }
        return false;
    }

    /* Comment when done. Here only for reference
        public SingleItemDrop(Item item, NBTTagCompound nbt, float chance, int min, int max, boolean looting_quantity, boolean looting_chance, DropContext[] conditions) {
        public SingleItemDrop(Item item, NBTTagCompound nbt, float chance, DropContext[] conditions) {
        public ItemGroup(float chance, int min, int max, boolean looting_chance, DropContext[] conditions, ItemGroupEntry... drops) {
        public ItemGroupEntry(Item item, NBTTagCompound nbt, int weight, int min_amount, int max_amount, boolean looting_quantity) {
        public ItemGroupEntry(Item item, NBTTagCompound nbt, int weight) {
    */

    public static void assign_drop_table(LOTREntityNPC entity) {
        if (entity instanceof LOTRTradeable || entity instanceof LOTRUnitTradeable) return;
        ((ILootableEntity)entity).set_pickpocket_chance(0.8F);

        DropTable table = new DropTable();
        DropContext[] default_context = new DropContext[] {DropContext.PICKPOCKET};
        table.drop_list.add(new SingleItemDrop(LOTRMod.silverCoin, null, 1.0F, 8, 32, false, false, default_context));
        if (entity instanceof LOTREntityMan) {
            table.drop_list.add(new SingleItemDrop(Items.cooked_chicken, null, 0.2F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(Items.book, null, 0.2F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(Items.bread, null, 0.2F, default_context));
            table.drop_list.add(new SingleItemDrop(CinderLoE.spiceHuman, null, 0.01F, default_context));
        } else if (entity instanceof LOTREntityOrc) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.orcSteel, null, 0.05F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.maggotyBread, null, 0.2F, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.manFlesh, null, 0.2F, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.elfBone, null, 0.2F, default_context));
            table.drop_list.add(new SingleItemDrop(Items.bone, null, 0.2F, default_context));
            table.drop_list.add(new SingleItemDrop(CinderLoE.spiceOrcish, null, 0.01F, default_context));
        } else if (entity instanceof LOTREntityElf) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.quenditeCrystal, null, 0.01F, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.lembas, null, 0.05F, default_context));
            table.drop_list.add(new SingleItemDrop(Item.getItemFromBlock(LOTRMod.niphredil), null, 0.1F, default_context));
            table.drop_list.add(new SingleItemDrop(Item.getItemFromBlock(LOTRMod.elanor), null, 0.1F, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.mallornNut, null, 0.05F, default_context));
            table.drop_list.add(new SingleItemDrop(CinderLoE.spiceElven, null, 0.01F, default_context));
        } else if (entity instanceof LOTREntityDwarf) {
            table.drop_list.add(new SingleItemDrop(CinderLoE.spiceDwarven, null, 0.01F, default_context));
            ItemGroupEntry amethyst = new ItemGroupEntry(LOTRMod.amethyst, null, 5);
            ItemGroupEntry topaz = new ItemGroupEntry(LOTRMod.topaz, null, 4);
            ItemGroupEntry amber = new ItemGroupEntry(LOTRMod.amber, null, 4);
            ItemGroupEntry opal = new ItemGroupEntry(LOTRMod.opal, null, 4);
            ItemGroupEntry sapphire = new ItemGroupEntry(LOTRMod.sapphire, null, 3);
            ItemGroupEntry ruby = new ItemGroupEntry(LOTRMod.ruby, null, 3);
            ItemGroupEntry emerald = new ItemGroupEntry(LOTRMod.emerald, null, 2);
            ItemGroupEntry diamond = new ItemGroupEntry(LOTRMod.diamond, null, 1);
            ItemGroup gem_drop = new ItemGroup(0.1F, 1, 1, false, default_context, amethyst, topaz, amber, opal, sapphire, ruby, emerald, diamond);
            table.drop_list.add(new SingleItemDrop(Items.coal, null, 0.1F, default_context));
            table.drop_list.add(new SingleItemDrop(Items.gold_nugget, null, 0.025F, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.ironNugget, null, 0.1F, default_context));
        }
        if (entity instanceof LOTREntityTauredain) {
            NBTTagCompound nbt = new NBTTagCompound();
            nbt.setTag("display", new NBTTagCompound());
            nbt.getCompoundTag("display").setString("Name", "§fChocolate chip cookie");
            table.drop_list.add(new SingleItemDrop(Items.cookie, nbt, 0.001F, default_context));
        } else if (entity instanceof LOTREntityRanger || entity instanceof LOTREntityGulfHaradrim || entity instanceof LOTREntityHarnedhrim || entity instanceof LOTREntityRohanMan) {
            table.drop_list.add(new SingleItemDrop(Items.leather, null, 1.0F, 1, 3, false, false, default_context));
        } else if (entity instanceof LOTREntityNomad) {
            table.drop_list.add(new SingleItemDrop(Item.getItemFromBlock(LOTRMod.driedReeds), null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.camelRaw, null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.camelCooked, null, 1.0F, 1, 3, false, false, default_context));
        }
        if (entity instanceof LOTREntityNearHaradrimBase || entity instanceof LOTREntityMoredain || entity instanceof LOTREntityTauredain) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.bronze, null, 1.0F, 1, 3, false, false, default_context));
        } else if (entity instanceof LOTREntityAngmarHillman || entity instanceof LOTREntityBreeMan || entity instanceof LOTREntityDaleMan || entity instanceof LOTREntityDorwinionMan || entity instanceof LOTREntityDunedain || entity instanceof LOTREntityDunlending || entity instanceof LOTREntityEasterling || entity instanceof LOTREntityGondorMan || entity instanceof LOTREntityRohanMan) {
            table.drop_list.add(new SingleItemDrop(Items.iron_ingot, null, 1.0F, 1, 3, false, false, default_context));
        } else if (entity instanceof LOTREntityHalfTroll) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.gemsbokHide, null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.gemsbokHorn, null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(Items.string, null, 1.0F, 2, 8, false, false, default_context));
        } else if (entity instanceof LOTREntityMordorOrc) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.nauriteGem, null, 1.0F, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.blackUrukSteel, null, 1.0F, 1, 3, false, false, default_context));
        } else if (entity instanceof LOTREntityDolGuldurOrc) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.mysteryWeb, null, 1.0F, default_context));
        } else if (entity instanceof LOTREntityGundabadOrc) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.urukSteel, null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.dwarfBone, null, 1.0F, default_context));
        } else if (entity instanceof LOTREntityUrukHai) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.urukSteel, null, 1.0F, 1, 3, false, false, default_context));
        } else if (entity instanceof LOTREntityDwarf && !(entity instanceof LOTREntityBlueDwarf) && !(entity instanceof RedDwarfWarrior) && !(entity instanceof RedDwarfBannerBearer) && !(entity instanceof RedDwarfArbalest)) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.dwarfSteel, null, 1.0F, 1, 3, false, false, default_context));
        } else if (entity instanceof LOTREntityBlueDwarf) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.blueDwarfSteel, null, 1.0F, 1, 3, false, false, default_context));
        } else if (entity instanceof RedDwarfWarrior || entity instanceof RedDwarfBannerBearer || entity instanceof RedDwarfArbalest) {
            table.drop_list.add(new SingleItemDrop(CinderLoE.redDwarfSteel, null, 1.0F, 1, 3, false, false, default_context));
        } else if (entity instanceof LOTREntityTree) {
            table.drop_list.add(new SingleItemDrop(Items.stick, null, 1.0F, 8, 32, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(Item.getItemFromBlock(LOTRMod.fangornPlant), null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(Item.getItemFromBlock(LOTRMod.fangornRiverweed), null, 1.0F, 1, 3, false, false, default_context));
        } else if (entity instanceof LOTREntityHobbit || entity instanceof LOTREntityGandalf) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.hobbitPipe, null, 1.0F, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.pipeweed, null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.hobbitPancake, null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.mugCider, null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.mushroomPie, null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(Items.mushroom_stew, null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(Items.apple, null, 1.0F, 1, 3, false, false, default_context));
            table.drop_list.add(new SingleItemDrop(Items.cake, null, 1.0F, 1, 3, false, false, default_context));
        } else if (entity instanceof LOTREntityUtumnoOrc) {
            table.drop_list.add(new SingleItemDrop(LOTRMod.mithrilNugget, null, 1.0F, default_context));
            table.drop_list.add(new SingleItemDrop(LOTRMod.chilling, null, 0.0001F, default_context));
        }
        ((ILootableEntity)entity).set_drop_table(table);
    }
}
