<commit_before>package mezz.jei.gui.recipes;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;

import com.google.common.collect.ImmutableList;
import mezz.jei.api.IRecipeRegistry;
import mezz.jei.api.recipe.IFocus;
import mezz.jei.api.recipe.IRecipeCategory;
import mezz.jei.api.recipe.IRecipeWrapper;
import mezz.jei.util.MathUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.inventory.Container;
import net.minecraft.item.ItemStack;

public class RecipeGuiLogic implements IRecipeGuiLogic {
	private static class State {
		@Nullable
		public final IFocus<?> focus;
		public final ImmutableList<IRecipeCategory> recipeCategories;

		public int recipeCategoryIndex;
		public int pageIndex;
		public int recipesPerPage;

		public State(@Nullable IFocus<?> focus, List<IRecipeCategory> recipeCategories, int recipeCategoryIndex, int pageIndex) {
			if (recipeCategories.isEmpty()) {
				throw new IllegalStateException("Recipe categories cannot be empty.");
			}
			this.focus = focus;
			this.recipeCategories = ImmutableList.copyOf(recipeCategories);
			this.recipeCategoryIndex = recipeCategoryIndex;
			this.pageIndex = pageIndex;
		}
	}

	@Nonnull
	private final IRecipeRegistry recipeRegistry;
	@Nonnull
	private final IRecipeLogicStateListener stateListener;

	private boolean initialState = true;
	@Nonnull
	private State state;
	@Nonnull
	private final Stack<State> history = new Stack<State>();

	/**
	 * List of recipes for the currently selected recipeClass
	 */
	private List<IRecipeWrapper> recipes = Collections.emptyList();

	public RecipeGuiLogic(IRecipeRegistry recipeRegistry, IRecipeLogicStateListener stateListener) {
		this.recipeRegistry = recipeRegistry;
		this.stateListener = stateListener;
		List<IRecipeCategory> recipeCategories = recipeRegistry.getRecipeCategories();
		this.state = new State(null, recipeCategories, 0, 0);
	}

	@Override
	public <V> boolean setFocus(IFocus<V> focus) {
		final List<IRecipeCategory> recipeCategories = recipeRegistry.getRecipeCategories(focus);
		if (recipeCategories.isEmpty()) {
			return false;
		}

		final int recipeCategoryIndex = getRecipeCategoryIndex(recipeCategories);

		if (!initialState) {
			history.push(this.state);
		}

		final State state = new State(focus, recipeCategories, recipeCategoryIndex, 0);
		setState(state);

		return true;
	}

	@Override
	public boolean back() {
		if (history.empty()) {
			return false;
		}
		final State state = history.pop();
		setState(state);
		return true;
	}

	@Override
	public void clearHistory() {
		while (!history.empty()) {
			history.pop();
		}
	}

	private void setState(State state) {
		this.state = state;
		this.initialState = false;
		updateRecipes();
		stateListener.onStateChange();
	}

	private int getRecipeCategoryIndex(List<IRecipeCategory> recipeCategories) {
		final Container container = Minecraft.getMinecraft().player.openContainer;
		if (container == null) {
			return 0;
		}

		for (int i = 0; i < recipeCategories.size(); i++) {
			IRecipeCategory recipeCategory = recipeCategories.get(i);
			if (recipeRegistry.getRecipeTransferHandler(container, recipeCategory) != null) {
				return i;
			}
		}

		return 0;
	}

	@Override
	public boolean setCategoryFocus() {
		IRecipeCategory recipeCategory = getSelectedRecipeCategory();

		if (!initialState) {
			history.push(this.state);
		}

		final List<IRecipeCategory> recipeCategories = recipeRegistry.getRecipeCategories();
		final int recipeCategoryIndex = recipeCategories.indexOf(recipeCategory);
		final State state = new State(null, recipeCategories, recipeCategoryIndex, 0);
		setState(state);

		return true;
	}

	@Override
	public boolean setCategoryFocus(List<String> recipeCategoryUids) {
		List<IRecipeCategory> recipeCategories = recipeRegistry.getRecipeCategories(recipeCategoryUids);
		if (recipeCategories.isEmpty()) {
			return false;
		}

		if (!initialState) {
			history.push(this.state);
		}

		final State state = new State(null, recipeCategories, 0, 0);
		setState(state);

		return true;
	}

	@Override
	public List<ItemStack> getRecipeCategoryCraftingItems() {
		IRecipeCategory category = getSelectedRecipeCategory();
		return getRecipeCategoryCraftingItems(category);
	}

	@Override
	public List<ItemStack> getRecipeCategoryCraftingItems(IRecipeCategory recipeCategory) {
		return recipeRegistry.getCraftingItems(recipeCategory, state.focus);
	}

	@Override
	public void setRecipesPerPage(int recipesPerPage) {
		if (state.recipesPerPage != recipesPerPage) {
			int recipeIndex = state.pageIndex * state.recipesPerPage;
			state.pageIndex = recipeIndex / recipesPerPage;

			state.recipesPerPage = recipesPerPage;
			updateRecipes();
		}
	}

	private void updateRecipes() {
		final IRecipeCategory recipeCategory = getSelectedRecipeCategory();
		IFocus<?> focus = state.focus;
		//noinspection unchecked
		this.recipes = recipeRegistry.getRecipeWrappers(recipeCategory, focus);
	}

	@Override
	public IRecipeCategory getSelectedRecipeCategory() {
		return state.recipeCategories.get(state.recipeCategoryIndex);
	}

	@Override
	public ImmutableList<IRecipeCategory> getRecipeCategories() {
		return state.recipeCategories;
	}

	@Override
	public List<RecipeLayout> getRecipeLayouts(int posX, int posY, int spacingY) {
		List<RecipeLayout> recipeLayouts = new ArrayList<RecipeLayout>();

		IRecipeCategory recipeCategory = getSelectedRecipeCategory();

		int recipeWidgetIndex = 0;
		for (int recipeIndex = state.pageIndex * state.recipesPerPage; recipeIndex < recipes.size() && recipeLayouts.size() < state.recipesPerPage; recipeIndex++) {
			IRecipeWrapper recipeWrapper = recipes.get(recipeIndex);<commit_msg>Fixes for "Use null focus instead of having focus mode NONE"<commit_after>package mezz.jei.gui.recipes;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;

import com.google.common.collect.ImmutableList;
import mezz.jei.api.IRecipeRegistry;
import mezz.jei.api.recipe.IFocus;
import mezz.jei.api.recipe.IRecipeCategory;
import mezz.jei.api.recipe.IRecipeWrapper;
import mezz.jei.util.MathUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.inventory.Container;
import net.minecraft.item.ItemStack;

public class RecipeGuiLogic implements IRecipeGuiLogic {
	private static class State {
		@Nullable
		public final IFocus<?> focus;
		public final ImmutableList<IRecipeCategory> recipeCategories;

		public int recipeCategoryIndex;
		public int pageIndex;
		public int recipesPerPage;

		public State(@Nullable IFocus<?> focus, List<IRecipeCategory> recipeCategories, int recipeCategoryIndex, int pageIndex) {
			if (recipeCategories.isEmpty()) {
				throw new IllegalStateException("Recipe categories cannot be empty.");
			}
			this.focus = focus;
			this.recipeCategories = ImmutableList.copyOf(recipeCategories);
			this.recipeCategoryIndex = recipeCategoryIndex;
			this.pageIndex = pageIndex;
		}
	}

	@Nonnull
	private final IRecipeRegistry recipeRegistry;
	@Nonnull
	private final IRecipeLogicStateListener stateListener;

	private boolean initialState = true;
	@Nonnull
	private State state;
	@Nonnull
	private final Stack<State> history = new Stack<State>();

	/**
	 * List of recipes for the currently selected recipeClass
	 */
	private List<IRecipeWrapper> recipes = Collections.emptyList();

	public RecipeGuiLogic(IRecipeRegistry recipeRegistry, IRecipeLogicStateListener stateListener) {
		this.recipeRegistry = recipeRegistry;
		this.stateListener = stateListener;
		List<IRecipeCategory> recipeCategories = recipeRegistry.getRecipeCategories();
		this.state = new State(null, recipeCategories, 0, 0);
	}

	@Override
	public <V> boolean setFocus(IFocus<V> focus) {
		final List<IRecipeCategory> recipeCategories = recipeRegistry.getRecipeCategories(focus);
		if (recipeCategories.isEmpty()) {
			return false;
		}

		final int recipeCategoryIndex = getRecipeCategoryIndex(recipeCategories);

		if (!initialState) {
			history.push(this.state);
		}

		final State state = new State(focus, recipeCategories, recipeCategoryIndex, 0);
		setState(state);

		return true;
	}

	@Override
	public boolean back() {
		if (history.empty()) {
			return false;
		}
		final State state = history.pop();
		setState(state);
		return true;
	}

	@Override
	public void clearHistory() {
		while (!history.empty()) {
			history.pop();
		}
	}

	private void setState(State state) {
		this.state = state;
		this.initialState = false;
		updateRecipes();
		stateListener.onStateChange();
	}

	private int getRecipeCategoryIndex(List<IRecipeCategory> recipeCategories) {
		final Container container = Minecraft.getMinecraft().player.openContainer;
		if (container == null) {
			return 0;
		}

		for (int i = 0; i < recipeCategories.size(); i++) {
			IRecipeCategory recipeCategory = recipeCategories.get(i);
			if (recipeRegistry.getRecipeTransferHandler(container, recipeCategory) != null) {
				return i;
			}
		}

		return 0;
	}

	@Override
	public boolean setCategoryFocus() {
		IRecipeCategory recipeCategory = getSelectedRecipeCategory();

		if (!initialState) {
			history.push(this.state);
		}

		final List<IRecipeCategory> recipeCategories = recipeRegistry.getRecipeCategories();
		final int recipeCategoryIndex = recipeCategories.indexOf(recipeCategory);
		final State state = new State(null, recipeCategories, recipeCategoryIndex, 0);
		setState(state);

		return true;
	}

	@Override
	public boolean setCategoryFocus(List<String> recipeCategoryUids) {
		List<IRecipeCategory> recipeCategories = recipeRegistry.getRecipeCategories(recipeCategoryUids);
		if (recipeCategories.isEmpty()) {
			return false;
		}

		if (!initialState) {
			history.push(this.state);
		}

		final State state = new State(null, recipeCategories, 0, 0);
		setState(state);

		return true;
	}

	@Override
	public List<ItemStack> getRecipeCategoryCraftingItems() {
		IRecipeCategory category = getSelectedRecipeCategory();
		return getRecipeCategoryCraftingItems(category);
	}

	@Override
	public List<ItemStack> getRecipeCategoryCraftingItems(IRecipeCategory recipeCategory) {
		return recipeRegistry.getCraftingItems(recipeCategory, state.focus);
	}

	@Override
	public void setRecipesPerPage(int recipesPerPage) {
		if (state.recipesPerPage != recipesPerPage) {
			int recipeIndex = state.pageIndex * state.recipesPerPage;
			state.pageIndex = recipeIndex / recipesPerPage;

			state.recipesPerPage = recipesPerPage;
			updateRecipes();
		}
	}

	private void updateRecipes() {
		final IRecipeCategory recipeCategory = getSelectedRecipeCategory();
		IFocus<?> focus = state.focus;
		if (focus != null) {
			//noinspection unchecked
			this.recipes = recipeRegistry.getRecipeWrappers(recipeCategory, focus);
		} else {
			//noinspection unchecked
			this.recipes = recipeRegistry.getRecipeWrappers(recipeCategory);
		}
	}

	@Override
	public IRecipeCategory getSelectedRecipeCategory() {
		return state.recipeCategories.get(state.recipeCategoryIndex);
	}

	@Override
	public ImmutableList<IRecipeCategory> getRecipeCategories() {
		return state.recipeCategories;
	}

	@Override
	public List<RecipeLayout> getRecipeLayouts(int posX, int posY, int spacingY) {
		List<RecipeLayout> recipeLayouts = new ArrayList<RecipeLayout>();

		IRecipeCategory recipeCategory = getSelectedRecipeCategory();

		int recipeWidgetIndex = 0;
		for (int recipeIndex = state.pageIndex * state.recipesPerPage; recipeIndex < recipes.size() && recipeLayouts.size() < state.recipesPerPage; recipeIndex++) {
			IRecipeWrapper recipeWrapper = recipes.get(recipeIndex);
{'fraction_non_alphanumeric': 0.09746522147307331, 'fraction_numerical': 0.0017069215669539984, 'mean_word_length': 5.29661472326706, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 47, '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': '6716251', 'n_tokens_mistral': 3873, 'n_tokens_neox': 3500, 'n_words': 789}