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

import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.components.AbstractWidget
import net.minecraft.client.gui.screens.Screen
import org.lwjgl.opengl.GL11

abstract class Widget2Panel<out S : Screen, T : AbstractWidget>(
	screen: S,
	parent: EditablePanel<*>?,
	x: Float,
	y: Float,
	width: Float,
	height: Float
) : EditablePanel<S>(screen, parent, x, y, width, height) {
	var widget: T? = null
		protected set

	var disableTicks = 0
		set(value) {
			field = value
			widget?.active = value > 0
		}

	val isWidgetDisabled: Boolean
		get() = disableTicks > 0

	override fun tickInner() {
		super.tickInner()

		if (disableTicks > 0) {
			disableTicks--
		}
	}

	private fun recreate() {
		if (widget == null) {
			return
		}

		val instance = makeNew()
		instance.visible = visible
		instance.x = absoluteX.toInt()
		instance.y = absoluteY.toInt()

		if (disableTicks > 0) {
			instance.active = false
		}

		val widget = widget
		if (widget != null)
			copyValues(instance, widget)

		this.widget = instance
		configureNew(instance, true)
	}

	override fun widthUpdated(new: Float, old: Float) {
		recreate()
	}

	override fun heightUpdated(new: Float, old: Float) {
		recreate()
	}

	override fun visibilityChanges(new: Boolean, old: Boolean) {
		widget?.visible = new
	}

	protected abstract fun copyValues(new_widget: T, old_widget: T)
	protected abstract fun makeNew(): T
	protected abstract fun configureNew(widget: T, recreation: Boolean)

	fun getOrCreateWidget(): T {
		val widget = this.widget
		if (widget != null) return widget

		val instance = makeNew()
		instance.visible = visible

		if (disableTicks > 0) {
			instance.active = false
		}

		configureNew(instance, false)

		this.widget = instance
		return instance
	}

	override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
		RenderSystem.depthFunc(GL11.GL_ALWAYS)
		getOrCreateWidget().render(graphics, mouseX.toInt(), mouseY.toInt(), partialTick)
		RenderSystem.depthFunc(GL11.GL_ALWAYS)
	}

	override fun charTypedInternal(codepoint: Char, mods: Int) = getOrCreateWidget().charTyped(codepoint, mods)
	override fun keyPressedInternal(key: Int, scancode: Int, mods: Int) = getOrCreateWidget().keyPressed(
		key,
		scancode,
		mods
	)
	override fun keyReleasedInternal(key: Int, scancode: Int, mods: Int) = getOrCreateWidget().keyReleased(key, scancode, mods)

	override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
		val (x1, y1) = screenToLocal(x, y)
		return getOrCreateWidget().mouseClicked(x1.toDouble(), y1.toDouble(), button)
	}

	override fun mouseReleasedInner(x: Double, y: Double, button: Int): Boolean {
		val (x1, y1) = screenToLocal(x, y)
		return getOrCreateWidget().mouseReleased(x1.toDouble(), y1.toDouble(), button)
	}
}
