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

import com.mojang.blaze3d.platform.InputConstants
import it.unimi.dsi.fastutil.booleans.BooleanConsumer
import net.minecraft.ChatFormatting
import net.minecraft.client.gui.GuiGraphics
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 ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.Widgets8
import ru.dbotthepony.mc.otm.client.render.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.client.screen.panels.button.CheckBoxLabelPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.SmallBooleanRectangleButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.SmallRectangleButtonPanel
import ru.dbotthepony.mc.otm.compat.cos.CosmeticToggleRenderButton
import ru.dbotthepony.mc.otm.compat.cos.isCosmeticArmorLoaded
import ru.dbotthepony.mc.otm.core.GetterSetter
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.asGetterOnly
import ru.dbotthepony.mc.otm.core.math.RGBAColor
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.MatteryPlayerNetworkChannel
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: MatteryPlayerCapability): 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()

	CheckBoxLabelPanel(
		screen,
		frame,
		text = TranslatableComponent("otm.gui.exopack.toggle_visibility"),
		isChecked = GetterSetter.of(
			{
				matteryPlayer.displayExoPack
			},
			{
				if (it) {
					MatteryPlayerNetworkChannel.sendToServer(DisplayExopackPacket)
				} else {
					MatteryPlayerNetworkChannel.sendToServer(HideExopackPacket)
				}
			}
		)
	).also {
		it.dock = Dock.TOP
		it.dockTop = 2f
	}

	CheckBoxLabelPanel(
		screen,
		frame,
		text = TranslatableComponent("otm.gui.exopack.toggle_glow"),
		isChecked = GetterSetter.of(
			{
				matteryPlayer.exopackGlows
			},
			{
				if (it) {
					MatteryPlayerNetworkChannel.sendToServer(EnableExopackGlowPacket)
				} else {
					MatteryPlayerNetworkChannel.sendToServer(DisableExopackGlowPacket)
				}
			}
		)
	).also {
		it.dock = Dock.TOP
		it.dockTop = 2f
	}

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

	ButtonPanel(screen, frame, label = TranslatableComponent("otm.gui.exopack.change_color2"), onPress = IntConsumer { MatteryPlayerNetworkChannel.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
		}

		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 != null && matteryPlayer.hasExoPack && screen is MatteryScreen<*>) {
					exosuitButton = SmallRectangleButtonPanel(screen, this, this.width - 2f - SmallBooleanRectangleButtonPanel.SIZE, 2f,
						skinElement = 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: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
			if (entity.isDeadOrDying) {
				return
			}

			val renderX = width.toInt() / 2
			val renderY = (height * 0.9f).toInt()

			InventoryScreen.renderEntityInInventoryFollowsMouse(
				graphics,
				renderX,
				renderY,
				renderScale,
				absoluteX.toInt() + renderX - mouseX,
				absoluteY + height * 0.15f - mouseY,
				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: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
		ExoPackInventoryScreen.ENTITY_RECTANGLE.render(graphics)
	}

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