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

import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexFormat
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.renderer.GameRenderer
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.inventory.InventoryMenu
import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions
import org.lwjgl.opengl.GL11
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.render.MatterySprite
import ru.dbotthepony.mc.otm.client.render.tesselator
import ru.dbotthepony.mc.otm.client.render.vertex
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.linearInterpolation
import ru.dbotthepony.mc.otm.core.util.formatFluidLevel
import ru.dbotthepony.mc.otm.menu.widget.FluidGaugeWidget

open class FluidGaugePanel<out S : Screen>(
	screen: S,
	parent: EditablePanel<*>? = null,
	val widget: FluidGaugeWidget,
	x: Float = 0f,
	y: Float = 0f
) : EditablePanel<S>(screen, parent, x, y, width = GAUGE.width, height = GAUGE.height) {
	init {
		scissor = true
	}

	protected open fun makeTooltip(): MutableList<Component> {
		return mutableListOf(
			if (widget.fluid.isEmpty) TranslatableComponent("otm.gui.empty") else TextComponent(String.format("%s: %.2f%%", widget.fluid.displayName.string, widget.percentage * 100.0)),
			formatFluidLevel(if (widget.fluid.isEmpty) 0 else widget.fluid.amount, widget.maxCapacity, formatAsReadable = ShiftPressedCond)
		)
	}

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

		return false
	}

	override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
		if (widget.percentage > 0.01f && widget.fluid.isNotEmpty) {
			val data = IClientFluidTypeExtensions.of(widget.fluid.fluid)
			val texture = data.stillTexture!!
			val sprite = minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(texture)!!
			val tint = RGBAColor.argb(data.getTintColor(widget.fluid))
			var height = (height * widget.percentage) / 16f
			var bottom = this.height

			val matrix = graphics.pose().last().pose()
			val builder = tesselator.builder

			builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX)

			while (height > 0.01f) {
				val thisHeight = height.coerceAtMost(1f)
				height -= thisHeight
				val actualHeight = thisHeight * 16f

				val interp = linearInterpolation(thisHeight, sprite.v1, sprite.v0)

				builder.vertex(matrix, 0f, bottom, 0f).uv(sprite.u0, sprite.v1).endVertex()
				builder.vertex(matrix, width, bottom, 0f).uv(sprite.u1, sprite.v1).endVertex()
				builder.vertex(matrix, width, bottom - actualHeight, 0f).uv(sprite.u1, interp).endVertex()
				builder.vertex(matrix, 0f, bottom - actualHeight, 0f).uv(sprite.u0, interp).endVertex()

				bottom -= actualHeight
			}

			RenderSystem.setShader(GameRenderer::getPositionTexShader)
			RenderSystem.enableBlend()
			RenderSystem.defaultBlendFunc()
			RenderSystem.depthFunc(GL11.GL_ALWAYS)

			RenderSystem.setShaderColor(tint.red, tint.green, tint.blue, tint.alpha)
			RenderSystem.setShaderTexture(0, sprite.atlasLocation())

			tesselator.end()

			RenderSystem.setShaderColor(1f, 1f, 1f, 1f)
			RenderSystem.depthFunc(GL11.GL_LESS)
		}

		GAUGE.render(graphics, 0f, 0f, width = width, height = height)
	}

	companion object {
		val GAUGE = MatterySprite.single(ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets/fluid_level.png"), 18f, 61f)
	}
}
