package mezz.jei.plugins.vanilla.crafting;

import java.util.ArrayList;
import java.util.List;

import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipe;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.RecipeManager;

import mezz.jei.api.recipe.category.IRecipeCategory;
import mezz.jei.util.ErrorUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public final class VanillaRecipeValidator {
	private static final Logger LOGGER = LogManager.getLogger();

	public static class Results {
		private final List<IRecipe> craftingRecipes = new ArrayList<>();
		private final List<FurnaceRecipe> furnaceRecipes = new ArrayList<>();

		public List<IRecipe> getCraftingRecipes() {
			return craftingRecipes;
		}

		public List<FurnaceRecipe> getFurnaceRecipes() {
			return furnaceRecipes;
		}
	}

	private VanillaRecipeValidator() {
	}

	public static Results getValidRecipes(IRecipeCategory<IRecipe> craftingCategory, IRecipeCategory<FurnaceRecipe> furnaceCategory) {
		CategoryRecipeValidator<IRecipe> craftingRecipesValidator = new CategoryRecipeValidator<>(craftingCategory, 9);
		CategoryRecipeValidator<FurnaceRecipe> furnaceRecipesValidator = new CategoryRecipeValidator<>(furnaceCategory, 1);

		Results results = new Results();
		WorldClient world = Minecraft.getInstance().world;
		RecipeManager recipeManager = world.getRecipeManager();
		for (IRecipe recipe : recipeManager.getRecipes()) {
			if (recipe instanceof FurnaceRecipe) {
				FurnaceRecipe furnaceRecipe = (FurnaceRecipe) recipe;
				if (furnaceRecipesValidator.isRecipeValid(furnaceRecipe)) {
					results.furnaceRecipes.add(furnaceRecipe);
				}
			} else {
				if (craftingRecipesValidator.isRecipeValid(recipe)) {
					results.craftingRecipes.add(recipe);
				}
			}
		}
		return results;
	}

	private static final class CategoryRecipeValidator<T extends IRecipe> {
		private static final int INVALID_COUNT = -1;
		private final IRecipeCategory<T> recipeCategory;
		private final int maxInputs;

		public CategoryRecipeValidator(IRecipeCategory<T> recipeCategory, int maxInputs) {
			this.recipeCategory = recipeCategory;
			this.maxInputs = maxInputs;
		}

		@SuppressWarnings("ConstantConditions")
		public boolean isRecipeValid(T recipe) {
			if (recipe.isDynamic()) {
				return false;
			}
			ItemStack recipeOutput = recipe.getRecipeOutput();
			if (recipeOutput == null || recipeOutput.isEmpty()) {
				String recipeInfo = getInfo(recipe);
				LOGGER.error("Recipe has no output. {}", recipeInfo);
				return false;
			}
			List<Ingredient> ingredients = recipe.getIngredients();
			if (ingredients == null) {
				String recipeInfo = getInfo(recipe);
				LOGGER.error("Recipe has no input Ingredients. {}", recipeInfo);
				return false;
			}
			int inputCount = getInputCount(ingredients);
			if (inputCount == INVALID_COUNT) {
				return false;
			} else if (inputCount > maxInputs) {
				String recipeInfo = getInfo(recipe);
				LOGGER.error("Recipe has too many inputs. {}", recipeInfo);
				return false;
			} else if (inputCount == 0) {
				String recipeInfo = getInfo(recipe);
				LOGGER.error("Recipe has no inputs. {}", recipeInfo);
				return false;
			}
			return true;
		}

		private String getInfo(T recipe) {
			return ErrorUtil.getInfoFromRecipe(recipe, recipeCategory);
		}

		@SuppressWarnings("ConstantConditions")
		protected static int getInputCount(List<Ingredient> ingredientList) {
			int inputCount = 0;
			for (Ingredient ingredient : ingredientList) {
				ItemStack[] input = ingredient.getMatchingStacks();
				if (input == null) {
					return INVALID_COUNT;
				} else {
					inputCount++;
				}
			}
			return inputCount;
		}
	}
}

@@ -89,16 +89,78 @@
 .List;%0A%0A
+import net.minecraftforge.common.crafting.VanillaRecipeTypes;%0A
 import n
@@ -1687,128 +1687,55 @@
 pes(
-)) %7B%0A%09%09%09if (recipe instanceof FurnaceRecipe) %7B%0A%09%09%09%09FurnaceRecipe furnaceRecipe = (FurnaceRecipe) recipe;
+VanillaRecipeTypes.CRAFTING)) %7B
 %0A%09%09%09
-%09
 if (
-furnace
+crafting
 Reci
@@ -1761,24 +1761,17 @@
 peValid(
-furnaceR
+r
 ecipe)) 
@@ -1776,25 +1776,24 @@
 ) %7B%0A%09%09%09%09
-%09
 results.
 furnaceR
@@ -1784,23 +1784,24 @@
 results.
-furnace
+crafting
 Recipes.
@@ -1804,24 +1804,17 @@
 pes.add(
-furnaceR
+r
 ecipe);%0A
@@ -1820,39 +1820,115 @@
 %0A%09%09%09
-%09
 %7D%0A
-%09
 %09%09%7D
- else
+%0A%09%09for (FurnaceRecipe recipe : recipeManager.getRecipes(VanillaRecipeTypes.SMELTING))
  %7B%0A
-%09
 %09%09%09if (
-crafting
+furnace
 Reci
@@ -1969,25 +1969,24 @@
 ) %7B%0A%09%09%09%09
-%09
 results.
 crafting
@@ -1973,32 +1973,31 @@
 %09%09%09%09results.
-crafting
+furnace
 Recipes.add(
@@ -2005,22 +2005,16 @@
 ecipe);%0A
-%09%09%09%09%7D%0A
 %09%09%09%7D%0A%09%09%7D

Fix #1528 Modded recipes also show up as crafting