package ihl.recipes;

import ic2.core.block.invslot.InvSlot;
import ic2.core.block.invslot.InvSlotConsumableItemStack;
import ihl.utils.IHLUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTank;
import net.minecraftforge.oredict.OreDictionary;

public class UniversalRecipeInput{

    private final List<FluidStack> fluidInputs;
    private final List<ItemStack> itemInputs;
    
    public UniversalRecipeInput(List<FluidStack> fluidInputs1, List<ItemStack> itemInputs1)
    {
    	fluidInputs=new ArrayList();
    	itemInputs=new ArrayList();
    	if(fluidInputs1!=null)fluidInputs.addAll(fluidInputs1);
    	if(itemInputs1!=null)itemInputs.addAll(itemInputs1);
    }
    
	public UniversalRecipeInput(FluidTank tank1, InvSlot inputSlot1) 
	{
    	fluidInputs=new ArrayList();
    	itemInputs=new ArrayList();
		List<FluidStack> fluidlist = new ArrayList();
		FluidStack inputFluid = null;
		if(tank1!=null && tank1.getFluid()!=null)
		{
			fluidInputs.add(tank1.getFluid());
		}
		for(int i=0; i<inputSlot1.size(); i++)
		{
			itemInputs.add(inputSlot1.get(i));
		}
	}

	public UniversalRecipeInput(ItemStack[] itemStacks) 
	{
    	fluidInputs=new ArrayList();
    	itemInputs=new ArrayList();

		for(int i=0;i<itemStacks.length;i++)
		{
			itemInputs.add(itemStacks[i]);
		}
	}

	public UniversalRecipeInput(FluidStack fs1) 
	{
    	fluidInputs=new ArrayList();
    	itemInputs=new ArrayList();

		fluidInputs.add(fs1);
	}

	public UniversalRecipeInput(FluidStack fluid, ItemStack[] itemStacks) {
    	fluidInputs=new ArrayList();
    	itemInputs=new ArrayList();

		fluidInputs.add(fluid);
		for(int i=0;i<itemStacks.length;i++)
		{
			itemInputs.add(itemStacks[i]);
		}
	}

	public UniversalRecipeInput(FluidStack[] fluidStacks) {
    	fluidInputs=new ArrayList();
    	itemInputs=new ArrayList();

		for(int i=0;i<fluidStacks.length;i++)
		{
			fluidInputs.add(fluidStacks[i]);
		}
	}

	public UniversalRecipeInput(ItemStack itemStack) 
	{
    	fluidInputs=new ArrayList();
    	itemInputs=new ArrayList();
		itemInputs.add(itemStack);
	}

	public boolean matches(List<FluidStack> fluidInputs1, List<ItemStack> itemInputs1) 
	{
		if(fluidInputs.size()!=fluidInputs1.size()||itemInputs.size()!=itemInputs1.size())
		{
			return false;
		}
		Iterator<FluidStack> fi1 = fluidInputs1.iterator();
		Iterator<ItemStack> ii1 = itemInputs1.iterator();
		Iterator<FluidStack> fi = fluidInputs.iterator();
		Iterator<ItemStack> ii = itemInputs.iterator();
		while(fi.hasNext())
		{
			FluidStack fs = fi.next();
			FluidStack fs1 = fi1.next();
			if(fs1==null || fs.getFluid()!=fs1.getFluid())
			{
				return false;
			}
		}
		while(ii.hasNext())
		{
			ItemStack is = ii.next();
			ItemStack is1 = ii1.next();
			if(IHLUtils.isItemsHaveSameOreDictionaryEntry(is, is1))
			{
				continue;
			}
			if(is==null)
			{
				return true;
			}
			if((is!=null && is1==null)||(is.getItem()!=is1.getItem()))
			{
				return false;
			}
			else if(is.getItemDamage()!=OreDictionary.WILDCARD_VALUE && is.getItemDamage()!=is1.getItemDamage())
			{
				return false;
			}
		}
		return true;
	}

	public List<FluidStack> getFluidInputs() {
		return fluidInputs;
	}
	
	public List<ItemStack> getItemInputs() {
		return itemInputs;
	}

	public boolean matches(UniversalRecipeInput input) {
		return this.matches(input.getFluidInputs(), input.getItemInputs());
	}
	
	public boolean adjustAmounts(List<FluidStack> fluidInputs1, List<ItemStack> itemInputs1, boolean doAdjustAmounts) 
	{
		if(fluidInputs.size()!=fluidInputs1.size()||itemInputs.size()!=itemInputs1.size())
		{
			return false;
		}
		Iterator<FluidStack> fi1 = fluidInputs1.iterator();
		Iterator<ItemStack> ii1 = itemInputs1.iterator();
		Iterator<FluidStack> fi = fluidInputs.iterator();
		Iterator<ItemStack> ii = itemInputs.iterator();
		while(fi.hasNext())
		{
			FluidStack fs = fi.next();
			FluidStack fs1 = fi1.next();
			if(fs.getFluid()!=fs1.getFluid() || fs1.amount<fs.amount)
			{
				return false;
			}
			else if(doAdjustAmounts)
			{
				fs1.amount-=fs.amount;
				if(fs1.amount<=0)fs1=null;
			}
		}
		while(ii.hasNext())
		{
			ItemStack is = ii.next();
			ItemStack is1 = ii1.next();
			if(is==null)
			{
				continue;
			}
			if(is1==null||!IHLUtils.isItemsHaveSameOreDictionaryEntry(is, is1) && is.getItem()!=is1.getItem())
			{
				return false;
			}
			else if((!IHLUtils.isItemsHaveSameOreDictionaryEntry(is, is1) && is.getItemDamage()!=OreDictionary.WILDCARD_VALUE && is.getItemDamage()!=is1.getItemDamage())  || is1.stackSize<is.stackSize)
			{
				return false;
			}
			else if(doAdjustAmounts)
			{
				is1.stackSize-=is.stackSize;
				if(is1.stackSize<=0)is1=null;
			}
		}
		return true;
	}

	public boolean adjustAmounts(UniversalRecipeInput input, boolean doAdjustAmounts) {
		return this.adjustAmounts(input.getFluidInputs(), input.getItemInputs(), doAdjustAmounts);
	}

	public boolean containItem(Item item) 
	{
		if(itemInputs==null || itemInputs.isEmpty())
		{
			return false;
		}
		Iterator<ItemStack> ii = itemInputs.iterator();
		while(ii.hasNext())
		{
			ItemStack is = ii.next();
			if(is!=null && is.getItem()==item)
			{
				return true;
			}
		}
		return false;
	}

	public ItemStack getItemStack(Item item) {
		if(itemInputs==null || itemInputs.isEmpty())
		{
			return null;
		}
		Iterator<ItemStack> ii = itemInputs.iterator();
		while(ii.hasNext())
		{
			ItemStack is = ii.next();
			if(is.getItem()==item)
			{
				return is;
			}
		}
		return null;
	}

	public int getMultiplierAndAdjustAmounts(UniversalRecipeInput input) 
	{
		List<FluidStack> fluidInputs1 = input.fluidInputs;
	    List<ItemStack> itemInputs1 = input.itemInputs;
	    int multiplier=Integer.MAX_VALUE;
		if(fluidInputs.size()!=fluidInputs1.size()||itemInputs.size()!=itemInputs1.size())
		{
			return 0;
		}
		Iterator<FluidStack> fi1 = fluidInputs1.iterator();
		Iterator<ItemStack> ii1 = itemInputs1.iterator();
		Iterator<FluidStack> fi = fluidInputs.iterator();
		Iterator<ItemStack> ii = itemInputs.iterator();
		while(fi.hasNext())
		{
			FluidStack fs = fi.next();
			FluidStack fs1 = fi1.next();
			if(fs.getFluid()!=fs1.getFluid() || fs1.amount<fs.amount)
			{
				return 0;
			}
			else
			{
				if(fs.amount>0)
				{
					int multiplier1=Math.floorDiv(fs1.amount,fs.amount);
					if(multiplier1<multiplier)
					{
						multiplier=multiplier1;
					}
					fs1.amount-=fs.amount*multiplier;
					if(fs1.amount<=0)fs1=null;
				}
			}
		}
		while(ii.hasNext())
		{
			ItemStack is = ii.next();
			ItemStack is1 = ii1.next();
			if(is==null)
			{
				continue;
			}
			if(is1==null|| !IHLUtils.isItemsHaveSameOreDictionaryEntry(is, is1) && is.getItem()!=is1.getItem())
			{
				return 0;
			}
			else if(!IHLUtils.isItemsHaveSameOreDictionaryEntry(is, is1) && is.getItemDamage()!=OreDictionary.WILDCARD_VALUE && is.getItemDamage()!=is1.getItemDamage())
			{
				return 0;
			}
			else if(is1.stackSize<is.stackSize)
			{
				return 0;
			}
			else
			{
				if(is.stackSize>0)
				{
					int multiplier1=Math.floorDiv(is1.stackSize,is.stackSize);
					if(multiplier1<multiplier)
					{
						multiplier=multiplier1;
					}
					is1.stackSize-=is.stackSize*multiplier;
					if(is1.stackSize<=0)is1=null;
				}
			}
		}
		if(multiplier<Integer.MAX_VALUE)
		{
			return multiplier;
		}
		else return 1;
	}

	public boolean containItemStack(ItemStack ingredient) 
	{
		if(itemInputs==null || itemInputs.isEmpty())
		{
			return false;
		}
		Iterator<ItemStack> ii = itemInputs.iterator();
		while(ii.hasNext())
		{
			ItemStack is = ii.next();
			if(is!=null && is.getItem()==ingredient.getItem() && (is.getItemDamage()==ingredient.getItemDamage() || is.getItemDamage()==OreDictionary.WILDCARD_VALUE))
			{
				return true;
			}
		}
		return false;
	}
}
