package org.cyclops.integrateddynamics.capability.energystorage;

import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import org.cyclops.integrateddynamics.block.BlockEnergyBatteryBase;
import org.cyclops.integrateddynamics.block.BlockEnergyBatteryConfig;
import org.cyclops.integrateddynamics.block.IEnergyContainerBlock;
import org.cyclops.integrateddynamics.core.item.ItemBlockEnergyContainer;

/**
 * Energy Battery implementation for ItemBlock's.
 * @author rubensworks
 */
public class EnergyStorageItemBlockEnergyContainer implements IEnergyStorageCapacity, IEnergyStorageMutable {

    private final ItemBlockEnergyContainer itemBlockEnergyContainer;
    private final ItemStack itemStack;
    private final int rate;

    public EnergyStorageItemBlockEnergyContainer(ItemBlockEnergyContainer itemBlockEnergyContainer, ItemStack itemStack, int rate) {
        this.itemBlockEnergyContainer = itemBlockEnergyContainer;
        this.itemStack = itemStack;
        this.rate = rate;

        if (!this.itemStack.hasTag()) {
            setItemStackEnergy(itemStack, 0);
        }
    }

    public EnergyStorageItemBlockEnergyContainer(ItemBlockEnergyContainer itemBlockEnergyContainer, ItemStack itemStack) {
        this(itemBlockEnergyContainer, itemStack, Integer.MAX_VALUE);
    }

    public int getRate() {
        return rate;
    }

    public boolean isCreative() {
        IEnergyContainerBlock block = itemBlockEnergyContainer.get();
        return block instanceof BlockEnergyBatteryBase && ((BlockEnergyBatteryBase) block).isCreative();
    }

    @Override
    public int getEnergyStored() {
        if(isCreative()) return Integer.MAX_VALUE;
        CompoundNBT tag = itemStack.getOrCreateTag();
        return tag.getInt(itemBlockEnergyContainer.get().getEneryContainerNBTName());
    }

    @Override
    public int getMaxEnergyStored() {
        if(isCreative()) return Integer.MAX_VALUE;
        CompoundNBT tag = itemStack.getOrCreateTag();
        if (!tag.contains(itemBlockEnergyContainer.get().getEneryContainerCapacityNBTName())) {
            return BlockEnergyBatteryConfig.capacity;
        }
        return tag.getInt(itemBlockEnergyContainer.get().getEneryContainerCapacityNBTName());
    }

    @Override
    public boolean canExtract() {
        return true;
    }

    @Override
    public boolean canReceive() {
        return true;
    }

    @Override
    public int receiveEnergy(int energy, boolean simulate) {
        if(isCreative()) return 0;
        energy = Math.min(energy, getRate());
        int stored = getEnergyStored();
        int energyReceived = Math.min(getMaxEnergyStored() - stored, energy);
        if(!simulate) {
            setItemStackEnergy(itemStack, stored + energyReceived);
        }
        return energyReceived;
    }

    @Override
    public int extractEnergy(int energy, boolean simulate) {
        if(isCreative()) return energy;
        energy = Math.min(energy, getRate());
        int stored = getEnergyStored();
        int newEnergy = Math.max(stored - energy, 0);
        if(!simulate) {
            setItemStackEnergy(itemStack, newEnergy);
        }
        return stored - newEnergy;
    }

    protected void setItemStackEnergy(ItemStack itemStack, int energy) {
        if(isCreative()) return;
        CompoundNBT tag = itemStack.getOrCreateTag();
        tag.putInt(itemBlockEnergyContainer.get().getEneryContainerNBTName(), energy);
    }

    @Override
    public void setCapacity(int capacity) {
        CompoundNBT tag = itemStack.getOrCreateTag();
        if (capacity == BlockEnergyBatteryConfig.capacity) {
            tag.remove(itemBlockEnergyContainer.get().getEneryContainerCapacityNBTName());
        } else {
            tag.putInt(itemBlockEnergyContainer.get().getEneryContainerCapacityNBTName(), capacity);
        }
    }

    @Override
    public void setEnergy(int energy) {
        setItemStackEnergy(itemStack, energy);
    }
}

@@ -1583,36 +1583,25 @@
  %7D%0A%0A    
-@Override%0A    public
+protected
  int get
@@ -1604,32 +1604,40 @@
  getEnergyStored
+Singular
 () %7B%0A        if(
@@ -1855,19 +1855,16 @@
  int get
-Max
 EnergySt
@@ -1868,24 +1868,147 @@
 yStored() %7B%0A
+        return getEnergyStoredSingular() * this.itemStack.getCount();%0A    %7D%0A%0A    public int getMaxEnergyStoredSingular() %7B%0A
         if(i
@@ -2353,32 +2353,164 @@
 Name());%0A    %7D%0A%0A
+    @Override%0A    public int getMaxEnergyStored() %7B%0A        return getMaxEnergyStoredSingular() * this.itemStack.getCount();%0A    %7D%0A%0A
     @Override%0A  
@@ -2755,16 +2755,96 @@
 turn 0;%0A
+        int stackSize = this.itemStack.getCount();%0A        energy /= stackSize;%0A
         
@@ -2909,32 +2909,40 @@
  getEnergyStored
+Singular
 ();%0A        int 
@@ -2985,16 +2985,24 @@
 gyStored
+Singular
 () - sto
@@ -3146,16 +3146,28 @@
 Received
+ * stackSize
 ;%0A    %7D%0A
@@ -3278,24 +3278,104 @@
 urn energy;%0A
+        int stackSize = this.itemStack.getCount();%0A        energy /= stackSize;%0A
         ener
@@ -3444,16 +3444,24 @@
 gyStored
+Singular
 ();%0A    
@@ -3613,16 +3613,17 @@
  return 
+(
 stored -
@@ -3628,24 +3628,37 @@
  - newEnergy
+) * stackSize
 ;%0A    %7D%0A%0A   

Allow draining/filling batteries in item-form when stacked