package advancedsystemsmanager.flow.execution;
import advancedsystemsmanager.api.execution.IItemBufferElement;
import advancedsystemsmanager.api.execution.IItemBufferSubElement;
import advancedsystemsmanager.flow.menus.MenuContainerScrap;
import advancedsystemsmanager.flow.menus.MenuCrafting;
import advancedsystemsmanager.flow.setting.CraftingSetting;
import advancedsystemsmanager.flow.setting.FuzzyMode;
import advancedsystemsmanager.flow.setting.Setting;
import advancedsystemsmanager.registry.SystemTypeRegistry;
import advancedsystemsmanager.tileentities.manager.TileEntityManager;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraftforge.fluids.FluidContainerRegistry;
import net.minecraftforge.fluids.FluidStack;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
public class CraftingBufferFluidElement implements IItemBufferElement, IItemBufferSubElement
{
public static final ItemStack DUMMY_ITEM = new ItemStack(Item.getItemById(1), 0, 0);
public static final double SPEED_MULTIPLIER = 0.05000000074505806D;
public static final Random rand = new Random();
// public CommandExecutor executor;
public MenuCrafting craftingMenu;
public MenuContainerScrap scrapMenu;
public IRecipe recipe;
public ItemStack result;
public boolean isCrafting;
public boolean justRemoved;
public int overflowBuffer;
public List<ItemStack> containerItems;
public List<IInventory> inventories = new ArrayList<IInventory>();
public CraftingBufferFluidElement(MenuCrafting craftingMenu, MenuContainerScrap scrapMenu)
{
// this.executor = executor;
this.craftingMenu = craftingMenu;
this.scrapMenu = scrapMenu;
this.recipe = craftingMenu.getDummy().getRecipe();
this.result = this.recipe == null ? null : this.recipe.getCraftingResult(craftingMenu.getDummy());
this.containerItems = new ArrayList<ItemStack>();
}
@Override
public void prepareSubElements()
{
this.isCrafting = true;
this.justRemoved = false;
}
@Override
public IItemBufferSubElement getSubElement()
{
if (this.isCrafting && this.result != null)
{
this.isCrafting = false;
return this;
} else
{
return null;
}
}
@Override
public void removeSubElement()
{
}
@Override
public int retrieveItemCount(int moveCount)
{
return moveCount;
}
@Override
public void decreaseStackSize(int moveCount)
{
}
@Override
public void releaseSubElements()
{
if (this.result != null)
{
if (this.overflowBuffer > 0)
{
ItemStack stack = this.result.copy();
stack.stackSize = this.overflowBuffer;
this.disposeOfExtraItem(stack);
this.overflowBuffer = 0;
}
for (ItemStack containerItem : this.containerItems)
{
this.disposeOfExtraItem(containerItem);
}
this.containerItems.clear();
}
}
public void disposeOfExtraItem(ItemStack itemStack)
{
TileEntityManager manager = this.craftingMenu.getParent().getManager();
List<SlotInventoryHolder> inventories = null;//CommandExecutor.getContainers(manager, this.scrapMenu, SystemTypeRegistry.INVENTORY);
for (SlotInventoryHolder inventoryHolder : inventories)
{
IInventory inventory = inventoryHolder.getInventory();
for (int i = 0; i < inventory.getSizeInventory(); ++i)
{
if (inventory.isItemValidForSlot(i, itemStack))
{
ItemStack stack = inventory.getStackInSlot(i);
if (stack == null || stack.isItemEqual(itemStack) && ItemStack.areItemStackTagsEqual(itemStack, stack) && itemStack.isStackable())
{
int itemCountInSlot = stack == null ? 0 : stack.stackSize;
int stackSize = Math.min(itemStack.stackSize, Math.min(inventory.getInventoryStackLimit(), itemStack.getMaxStackSize()) - itemCountInSlot);
if (stackSize > 0)
{
if (stack == null)
{
stack = itemStack.copy();
stack.stackSize = 0;
inventory.setInventorySlotContents(i, stack);
}
stack.stackSize += stackSize;
itemStack.stackSize -= stackSize;
inventory.markDirty();
if (itemStack.stackSize == 0)
{
return;
}
}
}
}
}
}
double x = (double)manager.xCoord + rand.nextDouble() * 0.8D + 0.1D;
double y = (double)manager.xCoord + rand.nextDouble() * 0.3D + 1.1D;
double z = (double)manager.xCoord + rand.nextDouble() * 0.8D + 0.1D;
EntityItem item = new EntityItem(manager.getWorldObj(), x, y, z, itemStack);
item.motionX = rand.nextGaussian() * SPEED_MULTIPLIER;
item.motionY = (rand.nextGaussian() + 4) * SPEED_MULTIPLIER;
item.motionZ = rand.nextGaussian() * SPEED_MULTIPLIER;
manager.getWorldObj().spawnEntityInWorld(item);
}
@Override
public void remove()
{
}
@Override
public void onUpdate()
{
for (IInventory inventory : this.inventories)
{
inventory.markDirty();
}
this.inventories.clear();
}
@Override
public int getSizeLeft()
{
if (!this.justRemoved)
{
return this.overflowBuffer > 0 ? this.overflowBuffer : (this.findItems(false) ? this.result.stackSize : 0);
} else
{
this.justRemoved = false;
return 0;
}
}
@Override
public int reduceBufferAmount(int amount)
{
this.justRemoved = true;
if (this.overflowBuffer > 0)
{
this.overflowBuffer -= amount;
} else
{
this.findItems(true);
this.overflowBuffer = this.result.stackSize - amount;
}
this.isCrafting = true;
return amount;
}
@Override
public ItemStack getKey()
{
if (this.useAdvancedDetection())
{
this.findItems(false);
}
return this.result;
}
@Override
public IInventory getContainer()
{
return null;
}
@Override
public IItemBufferSubElement getSplitElement(int elementAmount, int id, boolean fair)
{
return null;
}
@Override
public int getSlot()
{
return 0;
}
public boolean useAdvancedDetection()
{
return this.craftingMenu.getResultItem().getFuzzyMode() != FuzzyMode.PRECISE;
}
public boolean findItems(boolean remove)
{
List<CraftingSetting> settings = new ArrayList<CraftingSetting>();
for (Setting setting : this.craftingMenu.getSettings()) settings.add((CraftingSetting)setting);
HashMap<Integer, ItemStack> foundItems = new HashMap<Integer, ItemStack>();
// for (ItemBufferElement itemBufferElement : this.executor.itemBuffer)
// {
// int count = itemBufferElement.retrieveItemCount(9);
// Iterator iterator = itemBufferElement.getSubElements().iterator();
//
// while (iterator.hasNext())
// {
// IItemBufferSubElement itemBufferSubElement = (IItemBufferSubElement)iterator.next();
// ItemStack itemstack = itemBufferSubElement.getKey();
// int subCount = Math.min(count, itemBufferSubElement.getSizeLeft());
//
// for (int i = 0; i < 9; ++i)
// {
// CraftingSetting setting = settings.get(i);
// if (foundItems.get(i) == null)
// {
// if (!setting.isValid())
// {
// foundItems.put(i, DUMMY_ITEM);
// break;
// }
// if (subCount > 0 && setting.isEqualForCommandExecutor(itemstack))
// {
// foundItems.put(i, itemstack.copy());
// if (this.craftingMenu.getDummy().isItemValidForRecipe(this.recipe, this.craftingMenu.getResultItem(), foundItems, this.useAdvancedDetection()))
// {
// --subCount;
// --count;
// if (remove)
// {
// if (itemstack.getItem().hasContainerItem(itemstack))
// {
// this.containerItems.add(itemstack.getItem().getContainerItem(itemstack));
// }
//
// itemBufferElement.decreaseStackSize(1);
// itemBufferSubElement.reduceBufferAmount(1);
// if (itemBufferSubElement.getSizeLeft() == 0)
// {
// itemBufferSubElement.remove();
// iterator.remove();
// }
//
// this.inventories.add(((SlotStackInventoryHolder)itemBufferSubElement).getInventory());
// }
// } else
// {
// foundItems.remove(Integer.valueOf(i));
// }
// }
// }
// }
// }
// }
if (foundItems.size() < 9)
{
List<FluidElement> fluids = new ArrayList<FluidElement>();
for (int i = 0; i < 9; i++)
{
CraftingSetting setting = settings.get(i);
if (foundItems.get(i) == null && isBucket(setting))
{
boolean newFluid = true;
for (FluidElement fluidElement : fluids)
{
if (fluidElement.bucket.isItemEqual(setting.getItem()))
{
fluidElement.amountToFind += fluidElement.fluid.amount;
fluidElement.slots.add(i);
newFluid = false;
}
}
if (newFluid) fluids.add(new FluidElement(setting.getItem().copy(), i));
}
}
if (fluids.size() > 0)
{
// for (LiquidBufferElement liquidBufferElement : this.executor.liquidBuffer)
// {
// if (fluids.isEmpty()) break;
// Iterator<StackTankHolder> itr = liquidBufferElement.getHolders().iterator();
// while (itr.hasNext())
// {
// StackTankHolder tank = itr.next();
// for (Iterator<FluidElement> fluidItr = fluids.iterator(); fluidItr.hasNext(); )
// {
// FluidElement fluidElement = fluidItr.next();
// int maxAmount = liquidBufferElement.retrieveItemCount(fluidElement.amountToFind);
// if (tank.getFluidStack().isFluidEqual(fluidElement.fluid))
// {
// maxAmount = Math.min(maxAmount, tank.getSizeLeft());
// fluidElement.amountToFind -= maxAmount;
// if (remove)
// {
// tank.reduceAmount(maxAmount);
// FluidStack toRemove = fluidElement.fluid;
// toRemove.amount = maxAmount;
// tank.getTank().drain(tank.getSide(), maxAmount, true);
// }
// if (fluidElement.amountToFind == 0)
// {
// fluidItr.remove();
// for (int i : fluidElement.slots)
// foundItems.put(i, fluidElement.bucket);
// break;
// }
// }
// }
// if (tank.getSizeLeft() == 0) itr.remove();
// }
// }
}
}
if (foundItems.size() == 9)
{
this.result = this.craftingMenu.getDummy().getResult(foundItems);
this.result = this.result != null ? this.result.copy() : null;
return true;
} else
{
return false;
}
}
public static boolean isBucket(CraftingSetting setting)
{
return FluidContainerRegistry.isBucket(setting.getItem());
}
public static class FluidElement
{
public FluidStack fluid;
public ItemStack bucket;
public int amountToFind;
List<Integer> slots = new ArrayList<Integer>();
public FluidElement(ItemStack bucket, int i)
{
this.bucket = bucket;
this.fluid = FluidContainerRegistry.getFluidForFilledItem(bucket);
amountToFind = this.fluid.amount;
slots.add(i);
}
}
}