<commit_before>package mezz.jei.recipes;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMultimap;
import mezz.jei.Internal;
import mezz.jei.api.recipe.advanced.IRecipeManagerPlugin;
import mezz.jei.api.recipe.category.IRecipeCategory;
import mezz.jei.config.sorting.RecipeCategorySortingConfig;
import mezz.jei.gui.Focus;
import mezz.jei.ingredients.IngredientFilter;
import mezz.jei.ingredients.IngredientManager;
import mezz.jei.ingredients.Ingredients;
import mezz.jei.util.ErrorUtil;
import net.minecraft.resources.ResourceLocation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;

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

	private final IngredientManager ingredientManager;
	private final ImmutableList<IRecipeCategory<?>> recipeCategories;
	private final Set<ResourceLocation> hiddenRecipeCategoryUids = new HashSet<>();
	private @Nullable ImmutableList<IRecipeCategory<?>> recipeCategoriesVisibleCache = null;
	private final RecipeCategoryDataMap recipeCategoriesDataMap;
	private final Comparator<IRecipeCategory<?>> recipeCategoryComparator;
	private final RecipeMap recipeInputMap;
	private final RecipeMap recipeOutputMap;
	private final List<RecipeManagerPluginSafeWrapper> plugins = new ArrayList<>();

	public RecipeManagerInternal(
		ImmutableList<IRecipeCategory<?>> recipeCategories,
		ImmutableListMultimap<ResourceLocation, Object> recipes,
		ImmutableListMultimap<ResourceLocation, Object> recipeCatalysts,
		IngredientManager ingredientManager,
		ImmutableList<IRecipeManagerPlugin> plugins,
		RecipeCategorySortingConfig recipeCategorySortingConfig
	) {
		ErrorUtil.checkNotEmpty(recipeCategories, "recipeCategories");
		this.ingredientManager = ingredientManager;

		Collection<ResourceLocation> recipeCategoryResourceLocations = recipeCategories.stream()
			.map(IRecipeCategory::getUid)
			.toList();
		Comparator<ResourceLocation> recipeCategoryUidComparator = recipeCategorySortingConfig.getComparator(recipeCategoryResourceLocations);
		this.recipeInputMap = new RecipeMap(recipeCategoryUidComparator, ingredientManager);
		this.recipeOutputMap = new RecipeMap(recipeCategoryUidComparator, ingredientManager);
		this.recipeCategoryComparator = Comparator.comparing(IRecipeCategory::getUid, recipeCategoryUidComparator);
		this.recipeCategories = ImmutableList.sortedCopyOf(this.recipeCategoryComparator, recipeCategories);

		RecipeCatalystBuilder recipeCatalystBuilder = new RecipeCatalystBuilder(ingredientManager);
		for (IRecipeCategory<?> recipeCategory : recipeCategories) {
			ResourceLocation recipeCategoryUid = recipeCategory.getUid();
			if (recipeCatalysts.containsKey(recipeCategoryUid)) {
				List<Object> catalysts = recipeCatalysts.get(recipeCategoryUid);
				recipeCatalystBuilder.addCatalysts(recipeCategory, catalysts, recipeInputMap);
			}
		}
		ImmutableListMultimap<IRecipeCategory<?>, Object> recipeCatalystsMap = recipeCatalystBuilder.buildRecipeCatalysts();
		this.recipeCategoriesDataMap = new RecipeCategoryDataMap(recipeCategories, recipeCatalystsMap);

		ImmutableMultimap<String, ResourceLocation> categoriesForRecipeCatalystKeys = recipeCatalystBuilder.buildCategoriesForRecipeCatalystKeys();
		IRecipeManagerPlugin internalRecipeManagerPlugin = new InternalRecipeManagerPlugin(
			categoriesForRecipeCatalystKeys,
			ingredientManager,
			recipeCategoriesDataMap,
			recipeInputMap,
			recipeOutputMap,
			() -> getRecipeCategoriesStream(null, null, false)
		);
		this.plugins.add(new RecipeManagerPluginSafeWrapper(internalRecipeManagerPlugin));
		for (IRecipeManagerPlugin plugin : plugins) {
			this.plugins.add(new RecipeManagerPluginSafeWrapper(plugin));
		}

		addRecipes(recipes);
	}

	private void addRecipes(ImmutableListMultimap<ResourceLocation, Object> recipes) {
		Set<ResourceLocation> recipeCategoryUids = recipes.keySet();
		for (ResourceLocation recipeCategoryUid : recipeCategoryUids) {
			LOGGER.debug("Loading recipes: " + recipeCategoryUid.toString());
			for (Object recipe : recipes.get(recipeCategoryUid)) {
				addRecipeTyped(recipe, recipeCategoryUid);
			}
		}
	}

	private <T> void addRecipeTyped(T recipe, ResourceLocation recipeCategoryUid) {
		RecipeCategoryData<T> recipeCategoryData = recipeCategoriesDataMap.get(recipe, recipeCategoryUid);
		addRecipe(recipe, recipeCategoryData);
	}

	@Deprecated
	public <T> void addRecipe(T recipe, ResourceLocation recipeCategoryUid) {
		RecipeCategoryData<T> recipeCategoryData = recipeCategoriesDataMap.get(recipe, recipeCategoryUid);
		Set<T> hiddenRecipes = recipeCategoryData.getHiddenRecipes();
		if (hiddenRecipes.contains(recipe)) {
			unhideRecipe(recipe, recipeCategoryUid);
		} else {
			addRecipe(recipe, recipeCategoryData);
		}
	}

	private <T> void addRecipe(T recipe, RecipeCategoryData<T> recipeCategoryData) {
		IRecipeCategory<T> recipeCategory = recipeCategoryData.getRecipeCategory();
		try {
			Ingredients ingredients = new Ingredients();
			recipeCategory.setIngredients(recipe, ingredients);

			recipeInputMap.addRecipe(recipe, recipeCategory, ingredients.getInputIngredients());
			recipeOutputMap.addRecipe(recipe, recipeCategory, ingredients.getOutputIngredients());

			recipeCategoryData.getRecipes().add(recipe);<commit_msg>Fix #2506. Skip adding unhandled recipes<commit_after>package mezz.jei.recipes;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMultimap;
import mezz.jei.Internal;
import mezz.jei.api.recipe.advanced.IRecipeManagerPlugin;
import mezz.jei.api.recipe.category.IRecipeCategory;
import mezz.jei.config.sorting.RecipeCategorySortingConfig;
import mezz.jei.gui.Focus;
import mezz.jei.ingredients.IngredientFilter;
import mezz.jei.ingredients.IngredientManager;
import mezz.jei.ingredients.Ingredients;
import mezz.jei.util.ErrorUtil;
import net.minecraft.resources.ResourceLocation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;

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

	private final IngredientManager ingredientManager;
	private final ImmutableList<IRecipeCategory<?>> recipeCategories;
	private final Set<ResourceLocation> hiddenRecipeCategoryUids = new HashSet<>();
	private @Nullable ImmutableList<IRecipeCategory<?>> recipeCategoriesVisibleCache = null;
	private final RecipeCategoryDataMap recipeCategoriesDataMap;
	private final Comparator<IRecipeCategory<?>> recipeCategoryComparator;
	private final RecipeMap recipeInputMap;
	private final RecipeMap recipeOutputMap;
	private final List<RecipeManagerPluginSafeWrapper> plugins = new ArrayList<>();

	public RecipeManagerInternal(
		ImmutableList<IRecipeCategory<?>> recipeCategories,
		ImmutableListMultimap<ResourceLocation, Object> recipes,
		ImmutableListMultimap<ResourceLocation, Object> recipeCatalysts,
		IngredientManager ingredientManager,
		ImmutableList<IRecipeManagerPlugin> plugins,
		RecipeCategorySortingConfig recipeCategorySortingConfig
	) {
		ErrorUtil.checkNotEmpty(recipeCategories, "recipeCategories");
		this.ingredientManager = ingredientManager;

		Collection<ResourceLocation> recipeCategoryResourceLocations = recipeCategories.stream()
			.map(IRecipeCategory::getUid)
			.toList();
		Comparator<ResourceLocation> recipeCategoryUidComparator = recipeCategorySortingConfig.getComparator(recipeCategoryResourceLocations);
		this.recipeInputMap = new RecipeMap(recipeCategoryUidComparator, ingredientManager);
		this.recipeOutputMap = new RecipeMap(recipeCategoryUidComparator, ingredientManager);
		this.recipeCategoryComparator = Comparator.comparing(IRecipeCategory::getUid, recipeCategoryUidComparator);
		this.recipeCategories = ImmutableList.sortedCopyOf(this.recipeCategoryComparator, recipeCategories);

		RecipeCatalystBuilder recipeCatalystBuilder = new RecipeCatalystBuilder(ingredientManager);
		for (IRecipeCategory<?> recipeCategory : recipeCategories) {
			ResourceLocation recipeCategoryUid = recipeCategory.getUid();
			if (recipeCatalysts.containsKey(recipeCategoryUid)) {
				List<Object> catalysts = recipeCatalysts.get(recipeCategoryUid);
				recipeCatalystBuilder.addCatalysts(recipeCategory, catalysts, recipeInputMap);
			}
		}
		ImmutableListMultimap<IRecipeCategory<?>, Object> recipeCatalystsMap = recipeCatalystBuilder.buildRecipeCatalysts();
		this.recipeCategoriesDataMap = new RecipeCategoryDataMap(recipeCategories, recipeCatalystsMap);

		ImmutableMultimap<String, ResourceLocation> categoriesForRecipeCatalystKeys = recipeCatalystBuilder.buildCategoriesForRecipeCatalystKeys();
		IRecipeManagerPlugin internalRecipeManagerPlugin = new InternalRecipeManagerPlugin(
			categoriesForRecipeCatalystKeys,
			ingredientManager,
			recipeCategoriesDataMap,
			recipeInputMap,
			recipeOutputMap,
			() -> getRecipeCategoriesStream(null, null, false)
		);
		this.plugins.add(new RecipeManagerPluginSafeWrapper(internalRecipeManagerPlugin));
		for (IRecipeManagerPlugin plugin : plugins) {
			this.plugins.add(new RecipeManagerPluginSafeWrapper(plugin));
		}

		addRecipes(recipes);
	}

	private void addRecipes(ImmutableListMultimap<ResourceLocation, Object> recipes) {
		Set<ResourceLocation> recipeCategoryUids = recipes.keySet();
		for (ResourceLocation recipeCategoryUid : recipeCategoryUids) {
			LOGGER.debug("Loading recipes: " + recipeCategoryUid.toString());
			for (Object recipe : recipes.get(recipeCategoryUid)) {
				addRecipeTyped(recipe, recipeCategoryUid);
			}
		}
	}

	private <T> void addRecipeTyped(T recipe, ResourceLocation recipeCategoryUid) {
		RecipeCategoryData<T> recipeCategoryData = recipeCategoriesDataMap.get(recipe, recipeCategoryUid);
		addRecipe(recipe, recipeCategoryData);
	}

	@Deprecated
	public <T> void addRecipe(T recipe, ResourceLocation recipeCategoryUid) {
		RecipeCategoryData<T> recipeCategoryData = recipeCategoriesDataMap.get(recipe, recipeCategoryUid);
		Set<T> hiddenRecipes = recipeCategoryData.getHiddenRecipes();
		if (hiddenRecipes.contains(recipe)) {
			unhideRecipe(recipe, recipeCategoryUid);
		} else {
			addRecipe(recipe, recipeCategoryData);
		}
	}

	private <T> void addRecipe(T recipe, RecipeCategoryData<T> recipeCategoryData) {
		IRecipeCategory<T> recipeCategory = recipeCategoryData.getRecipeCategory();
		if (!recipeCategory.isHandled(recipe)) {
			return;
		}
		try {
			Ingredients ingredients = new Ingredients();
			recipeCategory.setIngredients(recipe, ingredients);

			recipeInputMap.addRecipe(recipe, recipeCategory, ingredients.getInputIngredients());
			recipeOutputMap.addRecipe(recipe, recipeCategory, ingredients.getOutputIngredients());

			recipeCategoryData.getRecipes().add(recipe);
{'fraction_non_alphanumeric': 0.08627209568199806, 'fraction_numerical': 0.0007035441034209832, 'mean_word_length': 7.747692307692308, 'pattern_counts': {'":': 0, '<': 67, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3869088', 'n_tokens_mistral': 3594, 'n_tokens_neox': 3307, 'n_words': 555}