package joshie.harvest.cooking;
import joshie.harvest.api.cooking.IFridge;
import joshie.harvest.api.cooking.Ingredient;
import joshie.harvest.api.cooking.IngredientStack;
import joshie.harvest.api.cooking.Recipe;
import joshie.harvest.cooking.recipe.RecipeMaker;
import joshie.harvest.cooking.tile.TileCooking;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static joshie.harvest.cooking.CookingHelper.PlaceIngredientResult.FAILURE;
import static joshie.harvest.cooking.CookingHelper.PlaceIngredientResult.SUCCESS;
import static joshie.harvest.core.lib.HFModInfo.MODID;
public class CookingHelper {
public static ItemStack getRecipe(String name) {
return HFCooking.RECIPE.getStackFromObject(Recipe.REGISTRY.get(new ResourceLocation(MODID, name)));
}
private static void addIngredientsToSet(Set<IngredientStack> ingredients, IInventory inventory) {
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack stack = inventory.getStackInSlot(i);
if (stack != null) {
Ingredient ingredient = CookingAPI.INSTANCE.getCookingComponents(stack);
if (ingredient != null) {
ingredients.add(new IngredientStack(ingredient, stack.stackSize));
}
}
}
}
private static boolean hasAllIngredients(Recipe recipe, List<IInventory> inventories) {
Set<IngredientStack> ingredients = new HashSet<>();
inventories.stream().forEach(inventory -> addIngredientsToSet(ingredients, inventory));
ingredients.remove(null); //Remove any nulls
return RecipeMaker.areAllRequiredInRecipe(recipe.getRequired(), ingredients);
}
public static List<IInventory> getAllFridges(EntityPlayer player, World world, BlockPos pos, int reach) {
List<IInventory> fridges = new ArrayList<>();
fridges.add(player.inventory);
for (int x = -reach; x <= reach; x++) {
for (int z = -reach; z <= reach; z++) {
for (int y = -1; y <= 1; y++) {
TileEntity tile = world.getTileEntity(pos.add(x, y, z));
if (tile instanceof IFridge) {
fridges.add(((IFridge)tile).getContents());
}
}
}
}
return fridges;
}
public static PlaceIngredientResult tryPlaceIngredients(EntityPlayer player, Recipe recipe) {
World world = player.worldObj;
BlockPos pos = new BlockPos(player);
int reach = player.capabilities.isCreativeMode ? 5 : 4;
List<IInventory> fridges = getAllFridges(player, world, pos, reach);
for (int x = -reach; x <= reach; x++) {
for (int z = -reach; z <= reach; z++) {
for (int y = -1; y <= 1; y++) {
TileEntity tile = world.getTileEntity(pos.add(x, y, z));
if (tile instanceof TileCooking) {
TileCooking cooking = (TileCooking) tile;
PlaceIngredientResult result = cooking.hasPrerequisites();
if (result != SUCCESS) return result;
if (cooking.getUtensil() == recipe.getUtensil() && cooking.getIngredients().size() == 0 && cooking.getResult().size() == 0) {
if (cook(cooking, recipe, fridges)) return SUCCESS;
}
}
}
}
}
return FAILURE;
}
public static ItemStack makeRecipe(Recipe recipe) {
return RecipeMaker.BUILDER.build(recipe, new ArrayList<>(recipe.getRequired())).get(0);
}
private static boolean isIngredient(IngredientStack ingredient, Ingredient check) {
return check != null && ingredient.isSame(new IngredientStack(check));
}
private static ItemStack getAndRemoveIngredient(IngredientStack ingredient, List<IInventory> fridges) {
for (IInventory inventory: fridges) {
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack stack = inventory.getStackInSlot(i);
if (stack != null && isIngredient(ingredient, CookingAPI.INSTANCE.getCookingComponents(stack))) {
return inventory.decrStackSize(i, 1);
}
}
}
return null;
}
private static boolean cook(TileCooking cooking, Recipe selected, List<IInventory> fridges) {
if (selected != null) {
if (!hasAllIngredients(selected, fridges)) return false;
else {
for (IngredientStack ingredient : selected.getRequired()) {
ItemStack ret = getAndRemoveIngredient(ingredient, fridges);
if (ret == null) return false;
else cooking.addIngredient(ret);
}
return true;
}
} else return false;
}
public enum PlaceIngredientResult {
SUCCESS, FAILURE, MISSING_OVEN, MISSING_COUNTER
}
}