package org.cyclops.cyclopscore.item;

import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.ItemFluidContainer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import java.util.List;

/**
 * This extension on {@link ItemFluidContainer} will show a damage indicator depending on how full
 * the container is. This can be used to hold certain amounts of Fluids in an Item.
 * When this item is available in a CreativeTab, it will add itself as a full and an empty container.
 * 
 * This container ONLY allows the fluid from the given type.
 * 
 * @author rubensworks
 *
 */
public abstract class DamageIndicatedItemFluidContainer extends ItemFluidContainer implements IInformationProvider {

    protected DamageIndicatedItemComponent component;
    protected Fluid fluid;
    
    /**
     * Create a new DamageIndicatedItemFluidContainer.
     * 
     * @param capacity
     *          The capacity this container will have.
     * @param fluid
     *          The Fluid instance this container must hold.
     */
    public DamageIndicatedItemFluidContainer(int capacity, Fluid fluid) {
        super(0, capacity);
        this.fluid = fluid;
        init();
    }
    
    private void init() {
        component = new DamageIndicatedItemComponent(this);
    }
    
    @Override
    public FluidStack drain(ItemStack container, int maxDrain, boolean doDrain) {
        if(container != null && container.getTagCompound() != null && container.getTagCompound().getCompoundTag("Fluid") != null) {
            // Fix for Thermal Expansion
            FluidStack stack = FluidStack.loadFluidStackFromNBT(container.getTagCompound().getCompoundTag("Fluid"));
            if(stack != null && stack.amount <= 0) {
                stack.amount = 0;
                NBTTagCompound fluidTag = container.getTagCompound().getCompoundTag("Fluid");
                fluidTag.setInteger("Amount", 0);
                return stack;
            }
        }
        if(container != null) {
            FluidStack fluidStack = super.drain(container, maxDrain, doDrain);
            if ((container.getTagCompound() == null || container.getTagCompound().getCompoundTag("Fluid") == null)) {
                fill(container, new FluidStack(fluid, 0), true);
            }
            return fluidStack;
        } else {
            return null;
        }
    }
    
    @Override
    public int fill(ItemStack container, FluidStack resource, boolean doFill) {
        int capacityOld = capacity;
        capacity = getCapacity(container);
        int filled = super.fill(container, resource, doFill);
        capacity = capacityOld;
        return filled;
    }
    
    @SuppressWarnings({ "rawtypes"})
    @Override
    @SideOnly(Side.CLIENT)
    public void getSubItems(Item item, CreativeTabs tab, List itemList) {
        component.getSubItems(item, tab, itemList, fluid, 0);
    }
    
    @Override
    public String getInfo(ItemStack itemStack) {
        return component.getInfo(itemStack);
    }
    
    @SuppressWarnings("rawtypes")
    @Override
    public void provideInformation(ItemStack itemStack, EntityPlayer entityPlayer, List list, boolean par4) {
        
    }
    
    @SuppressWarnings("rawtypes")
    @SideOnly(Side.CLIENT)
    @Override
    public void addInformation(ItemStack itemStack, EntityPlayer entityPlayer, List list, boolean par4) {
        component.addInformation(itemStack, entityPlayer, list, par4);
        super.addInformation(itemStack, entityPlayer, list, par4);
    }
    
    @Override
    public boolean showDurabilityBar(ItemStack stack) {
    	return true;
    }
    
    @Override
    public double getDurabilityForDisplay(ItemStack itemStack) {
    	return component.getDurability(itemStack);
    }
    
    /**
     * Get the fluid.
     * @return The fluid.
     */
    public Fluid getFluid() {
        return this.fluid;
    }
    
    /**
     * If the given amount can be drained. (Will drain in simulation mode)
     * @param amount The amount to try to drain.
     * @param itemStack The item stack to drain from.
     * @return If it could be drained.
     */
    public boolean canDrain(int amount, ItemStack itemStack) {
    	FluidStack simulatedDrain = drain(itemStack, amount, false);
    	return simulatedDrain != null && simulatedDrain.amount == amount;
    }

}

@@ -2746,24 +2746,137 @@
 n doFill) %7B%0A
+        if (fluid != null && resource != null && fluid != resource.getFluid()) %7B%0A            return 0;%0A        %7D%0A
         int 

Fix fluid container items being fillable with non-matching fluids, Closes CyclopsMC/EvilCraft#527