package mezz.jei.gui.ingredients;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;

import mezz.jei.api.gui.ITooltipCallback;
import mezz.jei.gui.Focus;
import mezz.jei.gui.TooltipRenderer;
import mezz.jei.util.CycleTimer;
import mezz.jei.util.Log;

public class GuiIngredient<T> extends Gui implements IGuiIngredient<T> {
	private final int slotIndex;
	private final boolean input;

	private final int xPosition;
	private final int yPosition;
	private final int width;
	private final int height;
	private final int padding;

	@Nonnull
	private final CycleTimer cycleTimer;
	@Nonnull
	private final List<T> contained = new ArrayList<>();
	@Nonnull
	private final IIngredientRenderer<T> ingredientRenderer;
	@Nonnull
	private final IIngredientHelper<T> ingredientHelper;
	@Nullable
	private ITooltipCallback<T> tooltipCallback;

	private boolean enabled;

	public GuiIngredient(@Nonnull IIngredientRenderer<T> ingredientRenderer, @Nonnull IIngredientHelper<T> ingredientHelper, int slotIndex, boolean input, int xPosition, int yPosition, int width, int height, int padding, int itemCycleOffset) {
		this.ingredientRenderer = ingredientRenderer;
		this.ingredientHelper = ingredientHelper;

		this.slotIndex = slotIndex;
		this.input = input;

		this.xPosition = xPosition;
		this.yPosition = yPosition;
		this.width = width;
		this.height = height;
		this.padding = padding;

		this.cycleTimer = new CycleTimer(itemCycleOffset);
	}

	@Override
	public void clear() {
		enabled = false;
		contained.clear();
	}

	@Override
	public boolean isMouseOver(int mouseX, int mouseY) {
		return enabled && (mouseX >= xPosition) && (mouseY >= yPosition) && (mouseX < xPosition + width) && (mouseY < yPosition + height);
	}

	@Override
	@Nullable
	public T get() {
		return cycleTimer.getCycledItem(contained);
	}

	@Nonnull
	@Override
	public List<T> getAll() {
		return contained;
	}

	@Override
	public void set(@Nonnull T contained, @Nonnull Focus focus) {
		set(Collections.singleton(contained), focus);
	}

	@Override
	public void set(@Nonnull Collection<T> contained, @Nonnull Focus focus) {
		this.contained.clear();
		contained = ingredientHelper.expandSubtypes(contained);
		T match = null;
		if ((isInput() && focus.getMode() == Focus.Mode.INPUT) || (!isInput() && focus.getMode() == Focus.Mode.OUTPUT)) {
			match = ingredientHelper.getMatch(contained, focus);
		}
		if (match != null) {
			this.contained.add(match);
		} else {
			this.contained.addAll(contained);
		}
		enabled = !this.contained.isEmpty();
	}

	public void setTooltipCallback(@Nullable ITooltipCallback<T> tooltipCallback) {
		this.tooltipCallback = tooltipCallback;
	}

	@Override
	public void draw(@Nonnull Minecraft minecraft) {
		cycleTimer.onDraw();

		T value = get();
		ingredientRenderer.draw(minecraft, xPosition + padding, yPosition + padding, value);
	}

	@Override
	public void drawHovered(@Nonnull Minecraft minecraft, int mouseX, int mouseY) {
		T value = get();
		if (value == null) {
			return;
		}
		draw(minecraft);
		drawTooltip(minecraft, mouseX, mouseY, value);
	}

	@Override
	public void drawHighlight(@Nonnull Minecraft minecraft, Color color, int xOffset, int yOffset) {
		int x = xPosition + xOffset;
		int y = yPosition + yOffset;
		GuiScreen.drawRect(x, y, x + width, y + height, color.getRGB());
	}

	private void drawTooltip(@Nonnull Minecraft minecraft, int mouseX, int mouseY, @Nonnull T value) {
		try {
			GlStateManager.disableDepth();

			RenderHelper.disableStandardItemLighting();
			drawRect(xPosition, yPosition, xPosition + width, yPosition + height, 0x7FFFFFFF);

			List<String> tooltip = ingredientRenderer.getTooltip(minecraft, value);

			if (tooltipCallback != null) {
				tooltipCallback.onTooltip(slotIndex, input, value, tooltip);
			}

			FontRenderer fontRenderer = ingredientRenderer.getFontRenderer(minecraft, value);
			TooltipRenderer.drawHoveringText(minecraft, tooltip, mouseX, mouseY, fontRenderer);

			GlStateManager.enableDepth();
		} catch (RuntimeException e) {
			Log.error("Exception when rendering tooltip on {}.", value, e);
		}
	}

	public boolean isInput() {
		return input;
	}
}

@@ -4063,16 +4063,26 @@
 Position
+ + padding
 , yPosit
@@ -4084,16 +4084,26 @@
 Position
+ + padding
 , xPosit
@@ -4113,16 +4113,26 @@
  + width
+ - padding
 , yPosit
@@ -4143,16 +4143,26 @@
 + height
+ - padding
 , 0x7FFF

Fix size of highlight on hovered ingredients