package me.loganb1max.minions.util;

import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.LeatherArmorMeta;

import java.util.Map;

public class ItemUtil {

    public static ItemStack setKeyInt(ItemStack itemStack, String key, int value) {
        net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack);
        nms.getTag().setInt(key, value);
        return CraftItemStack.asBukkitCopy(nms);
    }

    public static ItemStack setKeyDouble(ItemStack itemStack, String key, double value) {
        net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack);
        nms.getTag().setDouble(key, value);
        return CraftItemStack.asBukkitCopy(nms);
    }

    public static ItemStack setKeyString(ItemStack itemStack, String key, String value) {
        net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack);
        nms.getTag().setString(key, value);
        return CraftItemStack.asBukkitCopy(nms);
    }

    public static ItemStack setKeyLong(ItemStack itemStack, String key, long value) {
        net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack);
        nms.getTag().setLong(key, value);
        return CraftItemStack.asBukkitCopy(nms);
    }

    public static int getKeyInt(ItemStack itemStack, String key) {
        net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack);
        return nms.getTag().getInt(key);
    }

    public static double getKeyDouble(ItemStack itemStack, String key) {
        net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack);
        return nms.getTag().getDouble(key);
    }

    public static String getKeyString(ItemStack itemStack, String key) {
        net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack);
        return nms.getTag().getString(key);
    }

    public static long getKeyLong(ItemStack itemStack, String key) {
        net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack);
        return nms.getTag().getLong(key);
    }

    public static boolean hasKey(ItemStack itemStack, String key) {
        net.minecraft.server.v1_8_R3.ItemStack nms = CraftItemStack.asNMSCopy(itemStack);
        if (nms.getTag() == null) return false;
        return nms.getTag().hasKey(key);
    }

    public static ItemStack setMaxStackSize(ItemStack stack, int size) {
        try {
            net.minecraft.server.v1_8_R3.ItemStack item = CraftItemStack.asNMSCopy(stack);
            item.getItem().c(size);
            return CraftItemStack.asBukkitCopy(item);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }

    public static boolean areSimilar(ItemStack stack1, ItemStack stack2) {
    	if (stack1 != null && stack2 != null) {
    		if (stack1.getType() == stack2.getType()) {
    			if (stack1.getDurability() == stack2.getDurability()) {
    				if (stack1.getAmount() == stack2.getAmount()) {
    					if (stack1.hasItemMeta() && stack2.hasItemMeta()) {
    						if (stack1.getItemMeta().equals(stack2.getItemMeta())) {
    							return true;
							}
						} else {
    						return true;
						}
					}
				}
			}
		}
    	return false;
	}

    public static boolean consumeItem(Inventory inventory, int count, ItemStack itemStack) {
        Map<Integer, ? extends ItemStack> ammo = inventory.all(itemStack.getType());

        int found = 0;
        for (ItemStack stack : ammo.values()) {
			if (stack.getDurability() != itemStack.getDurability()) continue;
			if (!stack.getItemMeta().equals(itemStack.getItemMeta())) continue;
			found += stack.getAmount();
		}
        if (count > found)
            return false;

        for (Integer index : ammo.keySet()) {
            ItemStack stack = ammo.get(index);
			if (stack.getDurability() != itemStack.getDurability()) continue;
			if (!stack.getItemMeta().equals(itemStack.getItemMeta())) continue;
			int removed = Math.min(count, stack.getAmount());
			count -= removed;

			if (stack.getAmount() == removed)
				inventory.setItem(index, null);
			else
				stack.setAmount(stack.getAmount() - removed);

			if (count <= 0)
				break;
        }

		inventory.getViewers().stream().filter(humanEntity -> humanEntity instanceof Player).forEach(humanEntity -> ((Player)humanEntity).updateInventory());
        return true;
    }

	public static boolean containsItems(Inventory inventory, int count, ItemStack itemStack) {
		Map<Integer, ? extends ItemStack> ammo = inventory.all(itemStack.getType());

		int found = 0;
		for (ItemStack stack : ammo.values()) {
			if (stack.getDurability() != itemStack.getDurability()) continue;
			if (!stack.getItemMeta().equals(itemStack.getItemMeta())) continue;
			found += stack.getAmount();
		}
		if (count > found)
			return false;

		return true;
	}

	public static ItemStack fromConfigSection(final ConfigurationSection section) {
    	final Material material = Material.getMaterial(section.getString("Material"));
    	final int durability = section.getInt("Durability");
    	final ItemStack item = new ItemStack(material, 1);
    	item.setDurability((short) durability);
    	if (section.contains("Color") && material.name().toLowerCase().contains("leather")) {
			LeatherArmorMeta meta = (LeatherArmorMeta) item.getItemMeta();
    		int red = section.getInt("Color.Red");
			int green = section.getInt("Color.Green");
			int blue = section.getInt("Color.Blue");
			meta.setColor(Color.fromRGB(red, green, blue));
			item.setItemMeta(meta);
		}
    	return item;
	}

}
