package ru.dbotthepony.mc.otm.client.render.blockentity

import com.mojang.blaze3d.vertex.*
import com.mojang.math.Axis
import net.minecraft.client.renderer.*
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import net.minecraft.world.inventory.InventoryMenu
import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions
import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.linearInterpolation

class FluidTankRenderer(private val context: BlockEntityRendererProvider.Context) : BlockEntityRenderer<FluidTankBlockEntity> {
	private val fluidTop = 13f / 16f
	private val fluidBottom = 3f / 16f
	private val fluidHeight = 10f / 16f
	private val fluidWidth = 15.8f / 16f

	private val fluidPadding = (1f - fluidWidth) * .5f

	override fun render(
		tile: FluidTankBlockEntity,
		partialTick: Float,
		poseStack: PoseStack,
		bufferSource: MultiBufferSource,
		packedLight: Int,
		overlayLight: Int
	) {
		val fluid = tile.synchronizedFluid

		if (fluid.isEmpty)
			return

		val fluidLevel = fluid.amount.toFloat() / tile.fluid.getTankCapacity(0).toFloat()

		if (fluidLevel < 0.01f)
			return

		val data = IClientFluidTypeExtensions.of(fluid.fluid)
		val texture = data.stillTexture
		val sprite = minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(texture)
		val tint = RGBAColor.argb(data.getTintColor(fluid))
		val gas = fluid.fluid.fluidType.isLighterThanAir

		val interp = linearInterpolation(fluidLevel, sprite.v1, sprite.v0)
		val v1 = linearInterpolation(fluidBottom, sprite.v1, sprite.v0)

//		val lightLevel = fluid.fluid.fluidType.getLightLevel(fluid) // 0-15

		val builder = bufferSource.getBuffer(Sheets.translucentCullBlockSheet())

		poseStack.pushPose()
		poseStack.translate(0f, fluidBottom + (if (gas) 1f - fluidLevel else 0f) * fluidHeight, 0f)

		for (i in 0 .. 3) {
			poseStack.pushPose()

			poseStack.translate(0.5, 0.0, 0.5)
			poseStack.rotateAround(Axis.YP.rotationDegrees(i * 90.0f), 0.0f, 1.0f, 0.0f)
			poseStack.translate(-0.5f, 0f, fluidWidth * .5f)

			val matrix = poseStack.last().pose()

			builder.vertex(matrix, fluidPadding, 0f, 0f).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u0, v1).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()
			builder.vertex(matrix, fluidPadding + fluidWidth, 0f, 0f).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u1, v1).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()
			builder.vertex(matrix, fluidPadding + fluidWidth, fluidLevel * fluidHeight, 0f).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u1, interp).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()
			builder.vertex(matrix, fluidPadding, fluidLevel * fluidHeight, 0f).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u0, interp).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()

			poseStack.popPose()
		}

		val matrix = poseStack.last().pose()

		if (!gas && fluidLevel < 1f) { // top
			builder.vertex(matrix, fluidPadding, fluidLevel * fluidHeight, fluidPadding + fluidWidth).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u0, sprite.v1).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()
			builder.vertex(matrix, fluidPadding + fluidWidth, fluidLevel * fluidHeight, fluidPadding + fluidWidth).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u1, sprite.v1).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()
			builder.vertex(matrix, fluidPadding + fluidWidth, fluidLevel * fluidHeight, fluidPadding).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u1, sprite.v0).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()
			builder.vertex(matrix, fluidPadding, fluidLevel * fluidHeight, fluidPadding).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u0, sprite.v0).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()
		}

		if (gas && fluidLevel < 1f) { // bottom
			builder.vertex(matrix, fluidPadding, 0f, fluidPadding).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u0, sprite.v0).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()
			builder.vertex(matrix, fluidPadding + fluidWidth, 0f, fluidPadding).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u1, sprite.v0).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()
			builder.vertex(matrix, fluidPadding + fluidWidth, 0f, fluidPadding + fluidWidth).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u1, sprite.v1).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()
			builder.vertex(matrix, fluidPadding, 0f, fluidPadding + fluidWidth).color(tint.red, tint.green, tint.blue, tint.alpha).uv(sprite.u0, sprite.v1).overlayCoords(overlayLight).uv2(packedLight).normal(0.0f, 1.0f, 0.0f).endVertex()
		}

		poseStack.popPose()
	}
}
