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

import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
import net.minecraft.client.gui.screens.inventory.InventoryScreen
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.neoforged.neoforge.network.PacketDistributor
import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.Widgets8
import ru.dbotthepony.mc.otm.client.render.sprites.sprite
import ru.dbotthepony.mc.otm.client.screen.ExopackInventoryScreen
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.button.ButtonPanel
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleRenderButton
import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorLoaded
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.mc.otm.client.screen.panels.button.BooleanButtonPanel
import ru.dbotthepony.mc.otm.network.DisableExopackGlowPacket
import ru.dbotthepony.mc.otm.network.DisplayExopackPacket
import ru.dbotthepony.mc.otm.network.EnableExopackGlowPacket
import ru.dbotthepony.mc.otm.network.HideExopackPacket
import ru.dbotthepony.mc.otm.network.ResetExopackColorPacket
import ru.dbotthepony.mc.otm.network.SetExopackColorPacket
import java.util.function.IntConsumer

private fun calculateScale(width: Float, height: Float): Int {
	val aspectRatio = width / height

	if (aspectRatio.isNaN()) {
		return 1
	}

	if (aspectRatio < 0.7083) {
		return (width / 51f * 30f).toInt()
	} else {
		return (height / 72f * 30f).toInt()
	}
}

private fun createExopackAppearanceWindow(screen: MatteryScreen<*>, matteryPlayer: MatteryPlayer): FramePanel<*> {
	val frame = FramePanel.padded(screen, width = 200f, height = 90f, title = TranslatableComponent("otm.gui.exopack.customization"))

	screen.addPanel(frame)

	frame.toScreenCenter()
	frame.behaveAsWindow()
	frame.requestFocus()

	BooleanButtonPanel.Checkbox(
		screen,
		frame,
		label = TranslatableComponent("otm.gui.exopack.toggle_visibility"),
		prop = Delegate.Of(
			{
				matteryPlayer.isExopackVisible
			},
			{
				if (it) {
					PacketDistributor.sendToServer(DisplayExopackPacket)
				} else {
					PacketDistributor.sendToServer(HideExopackPacket)
				}
			}
		)
	).also {
		it.dock = Dock.TOP
		it.dockTop = 2f
	}

	BooleanButtonPanel.Checkbox(
		screen,
		frame,
		label = TranslatableComponent("otm.gui.exopack.toggle_glow"),
		prop = Delegate.Of(
			{
				matteryPlayer.exopackGlows
			},
			{
				if (it) {
					PacketDistributor.sendToServer(EnableExopackGlowPacket)
				} else {
					PacketDistributor.sendToServer(DisableExopackGlowPacket)
				}
			}
		)
	).also {
		it.dock = Dock.TOP
		it.dockTop = 2f
	}

	ButtonPanel.Simple(screen, frame, label = TranslatableComponent("otm.gui.exopack.change_color"), onPress = IntConsumer {
		frame.blockingWindow = ColorPickerPanel.frame(
			screen,
			callback = { PacketDistributor.sendToServer(SetExopackColorPacket(it)) },
			color = matteryPlayer.exopackColor ?: RGBAColor.WHITE,
			title = TranslatableComponent("otm.gui.exopack.change_color"))
	}).also {
		it.dock = Dock.TOP
		it.dockTop = 2f
	}

	ButtonPanel.Simple(screen, frame, label = TranslatableComponent("otm.gui.exopack.change_color2"), onPress = IntConsumer { PacketDistributor.sendToServer(ResetExopackColorPacket) }).also {
		it.dock = Dock.TOP
		it.dockTop = 2f
	}

	return frame
}

class EntityRendererPanel<out S : Screen> @JvmOverloads constructor(
	screen: S,
	parent: EditablePanel<*>?,
	val entity: LivingEntity,
	x: Float = 0f,
	y: Float = 0f,
	width: Float = ENTITY_RECTANGLE.width,
	height: Float = ENTITY_RECTANGLE.height,
	var renderScale: Int = calculateScale(width, height)
) : EditablePanel<S>(screen, parent, x, y, width, height) {
	init {
		dockPadding = DockProperty(1f, 1f, 1.5f, 1f)
	}

	val canvas = object : EditablePanel<S>(screen, this@EntityRendererPanel) {
		init {
			dock = Dock.FILL
			scissor = true
			scissorLock = true
		}

		private val cosButton: EditablePanel<S>?
		private val exosuitButton: EditablePanel<S>?

		init {
			if (entity is Player && isCosmeticArmorLoaded) {
				cosButton = CosmeticToggleRenderButton(screen, this, x = this.width - 7f, y = this.height - 7f)
			} else {
				cosButton = null
			}

			if (entity is Player) {
				val matteryPlayer = entity.matteryPlayer

				if (matteryPlayer.hasExopack && screen is MatteryScreen<*>) {
					exosuitButton = ButtonPanel.square8(screen, this, this.width - 2f - 8f, 2f,
						icon = Widgets8.EXOPACK_SHOWN,
						onPress = {
							blockingWindow = createExopackAppearanceWindow(screen, matteryPlayer)
						}
					)

					exosuitButton.tooltips.add(TranslatableComponent("otm.gui.exopack.customize"))
				} else {
					exosuitButton = null
				}
			} else {
				exosuitButton = null
			}
		}

		override fun innerRender(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
			if (entity.isDeadOrDying) {
				return
			}

			InventoryScreen.renderEntityInInventoryFollowsMouse(
				graphics.parent,
				0, 0,
				this.width.toInt(), this.height.toInt(),
				renderScale,
				0f,
				mouseX - absoluteX.toInt(),
				mouseY - absoluteY + height * 0.15f,
				entity
			)
		}

		override fun performLayout() {
			super.performLayout()

			if (cosButton != null) {
				cosButton.x = this.width - 7f
				cosButton.y = this.height - 7f
			}

			if (exosuitButton != null) {
				exosuitButton.x = this.width - 2f - exosuitButton.width
				exosuitButton.y = 2f
			}
		}
	}

	override fun innerRender(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
		ExopackInventoryScreen.ENTITY_RECTANGLE.render(graphics)
	}

	companion object {
		val ENTITY_RECTANGLE = AbstractContainerScreen.INVENTORY_LOCATION.sprite(25f, 7f, 51f, 72f)
	}
}
