package ru.dbotthepony.mc.otm.client.screen.widget

import com.mojang.blaze3d.platform.InputConstants
import com.mojang.blaze3d.systems.RenderSystem
import mezz.jei.api.recipe.RecipeType
import net.minecraft.ChatFormatting
import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component
import ru.dbotthepony.mc.otm.client.CursorType
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.UVWindingOrder
import ru.dbotthepony.mc.otm.client.render.WidgetLocation
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.AbstractButtonPanel
import ru.dbotthepony.mc.otm.compat.jei.JEIPlugin
import ru.dbotthepony.mc.otm.compat.jei.isJeiLoaded
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.menu.widget.IProgressGaugeWidget
import java.util.function.Supplier
import kotlin.math.roundToInt

open class ProgressGaugePanel<out S : Screen>(
	screen: S,
	parent: EditablePanel<*>? = null,
	val widget: IProgressGaugeWidget,
	x: Float = 0f,
	y: Float = 0f
): AbstractButtonPanel<S>(screen, parent, x, y) {
	init {
		scissor = true
	}

	var flop = false
	var type = Type.PROGRESS
		set(value) {
			field = value
			width = value.width
			height = value.height
		}

	var behaviorType: Type? = null

	init {
		type = Type.PROGRESS
	}

	private var recipeTypeSupplier: Supplier<List<RecipeType<*>>>? = null

	enum class Type(val width: Float, val height: Float) {
		PROGRESS(GAUGE_BACKGROUND.width, GAUGE_BACKGROUND.height),
		FUEL(FUEL_BACKGROUND.width, FUEL_BACKGROUND.height);

		val localizedString = "otm.gui.${name.lowercase()}_widget"
	}

	protected open fun makeTooltip(): MutableList<Component> {
		val tooltip = ArrayList<Component>()

		if (widget is IProgressGaugeWidget.WithTicks) {
			tooltip.add(
				TranslatableComponent(
					"${(behaviorType ?: type).localizedString}_ticks",
					widget.workTicks,
					widget.totalTicks,
					String.format("%.2f", widget.progress * 100f)
				)
			)
		} else {
			tooltip.add(
				TranslatableComponent(
					(behaviorType ?: type).localizedString,
					String.format("%.2f", widget.progress * 100f)
				)
			)
		}

		if (widget.isStuck) {
			tooltip.add(TranslatableComponent("otm.gui.progress_stuck").withStyle(ChatFormatting.DARK_RED))
		}

		if (tooltips.isNotEmpty()) {
			tooltip.add(TextComponent(""))
			tooltip.addAll(tooltips)
		}

		return tooltip
	}

	override fun innerRender(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
		if (widget.isStuck && tickCount % 40 <= 20) {
			RenderSystem.setShaderColor(0.75f, 0.4f, 0.4f, 1f)
		}

		when (type) {
			Type.PROGRESS -> {
				if (flop) {
					GAUGE_BACKGROUND.render(graphics, canvasHeight = height, canvasWidth = this.width, winding = UVWindingOrder.U1_V0_U0_V1)
					val width = (this.width * widget.progress).roundToInt().toFloat()
					GAUGE_FOREGROUND.renderPartial(graphics, x = this.width - width, height = height, width = width, winding = UVWindingOrder.U1_V0_U0_V1)
				} else {
					GAUGE_BACKGROUND.render(graphics, canvasHeight = height, canvasWidth = this.width)
					val width = (this.width * widget.progress).roundToInt().toFloat()
					GAUGE_FOREGROUND.renderPartial(graphics, height = height, width = width)
				}
			}

			Type.FUEL -> {
				FUEL_BACKGROUND.render(graphics, canvasHeight = height, canvasWidth = this.width)
				val height = (this.height * widget.progress).roundToInt().toFloat()
				FUEL_FOREGROUND.renderPartial(graphics, height = height, y = this.height - height, topDown = false, width = width)
			}
		}

		if (widget.isStuck && tickCount % 40 <= 20) {
			RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
		}
	}

	override fun innerRenderTooltips(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float): Boolean {
		if (shouldRenderTooltips(graphics, mouseX, mouseY, partialTick)) {
			graphics.renderComponentTooltip(font, makeTooltip(), mouseX.toInt(), mouseY.toInt())
			return true
		}

		return false
	}

	override fun test(value: Int): Boolean {
		return recipeTypeSupplier != null && value == InputConstants.MOUSE_BUTTON_LEFT
	}

	override val cursorType: CursorType
		get() = if (recipeTypeSupplier != null) CursorType.HAND else CursorType.ARROW

	override fun onClick(mouseButton: Int) {
		val recipeTypeSupplier = recipeTypeSupplier ?: return
		JEIPlugin.RUNTIME.recipesGui.showTypes(recipeTypeSupplier.get())
	}

	private fun setRecipeType0(provider: Supplier<List<RecipeType<*>>>) {
		recipeTypeSupplier = provider
	}

	fun setRecipeType(provider: Supplier<List<RecipeType<*>>>) {
		if (isJeiLoaded) {
			setRecipeType0(provider)
		}
	}

	companion object {
		val GAUGE_BACKGROUND = WidgetLocation.PROGRESS_ARROWS.sprite(y = 0f, width = 22f, height = 15f)
		val GAUGE_FOREGROUND = WidgetLocation.PROGRESS_ARROWS.sprite(y = 15f, width = 22f, height = 15f)
		val FUEL_BACKGROUND = WidgetLocation.FUEL.sprite(y = 0f, width = 14f, height = 14f)
		val FUEL_FOREGROUND = WidgetLocation.FUEL.sprite(y = 14f, width = 14f, height = 14f)
	}
}
