package WayofTime.alchemicalWizardry.api.items;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import net.minecraft.block.Block;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.ShapelessRecipes;
import net.minecraft.world.World;
import net.minecraftforge.oredict.OreDictionary;
import WayofTime.alchemicalWizardry.api.items.interfaces.IBloodOrb;

/** Shapeless Blood Orb Recipe Handler by joshie **/
public class ShapelessBloodOrbRecipe implements IRecipe {
	private ItemStack output = null;
	private ArrayList<Object> input = new ArrayList<Object>();

	public ShapelessBloodOrbRecipe(Block result, Object... recipe) {
		this(new ItemStack(result), recipe);
	}

	public ShapelessBloodOrbRecipe(Item result, Object... recipe) {
		this(new ItemStack(result), recipe);
	}

	public ShapelessBloodOrbRecipe(ItemStack result, Object... recipe) {
		output = result.copy();
		for (Object in : recipe) {
			if (in instanceof ItemStack) {
				input.add(((ItemStack) in).copy());
			} else if (in instanceof IBloodOrb) { //If the item is an instanceof IBloodOrb then save the level of the orb
				input.add((Integer)(((IBloodOrb)in).getOrbLevel()));
			} else if (in instanceof Item) {
				input.add(new ItemStack((Item) in));
			} else if (in instanceof Block) {
				input.add(new ItemStack((Block) in));
			} else if (in instanceof String) {
				input.add(OreDictionary.getOres((String) in));
			} else {
				String ret = "Invalid shapeless ore recipe: ";
				for (Object tmp : recipe) {
					ret += tmp + ", ";
				}
				ret += output;
				throw new RuntimeException(ret);
			}
		}
	}

	@SuppressWarnings("unchecked")
	ShapelessBloodOrbRecipe(ShapelessRecipes recipe, Map<ItemStack, String> replacements) {
		output = recipe.getRecipeOutput();

		for (ItemStack ingred : ((List<ItemStack>) recipe.recipeItems)) {
			Object finalObj = ingred;
			for (Entry<ItemStack, String> replace : replacements.entrySet()) {
				if (OreDictionary.itemMatches(replace.getKey(), ingred, false)) {
					finalObj = OreDictionary.getOres(replace.getValue());
					break;
				}
			}
			input.add(finalObj);
		}
	}

	@Override
	public int getRecipeSize() {
		return input.size();
	}

	@Override
	public ItemStack getRecipeOutput() {
		return output;
	}

	@Override
	public ItemStack getCraftingResult(InventoryCrafting var1) {
		return output.copy();
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean matches(InventoryCrafting var1, World world) {
		ArrayList<Object> required = new ArrayList<Object>(input);

		for (int x = 0; x < var1.getSizeInventory(); x++) {
			ItemStack slot = var1.getStackInSlot(x);

			if (slot != null) {
				boolean inRecipe = false;
				Iterator<Object> req = required.iterator();

				while (req.hasNext()) {
					boolean match = false;

					Object next = req.next();

					//If target is integer, then we should be check the blood orb value of the item instead
					if(next instanceof Integer) {
						if(slot != null && slot.getItem() instanceof IBloodOrb) {
							IBloodOrb orb = (IBloodOrb) slot.getItem();
							if(orb.getOrbLevel() < (Integer)next) {
								return false;
							}
						} else return false;
					} else if (next instanceof ItemStack) {
						match = OreDictionary.itemMatches((ItemStack) next, slot, false);
					} else if (next instanceof ArrayList) {
						Iterator<ItemStack> itr = ((ArrayList<ItemStack>) next).iterator();
						while (itr.hasNext() && !match) {
							match = OreDictionary.itemMatches(itr.next(), slot, false);
						}
					}

					if (match) {
						inRecipe = true;
						required.remove(next);
						break;
					}
				}

				if (!inRecipe) {
					return false;
				}
			}
		}

		return required.isEmpty();
	}

	public ArrayList<Object> getInput() {
		return this.input;
	}
}