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

import net.minecraft.ChatFormatting
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.network.chat.Component
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.neoforged.neoforge.common.Tags
import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.block.entity.decorative.PainterBlockEntity
import ru.dbotthepony.mc.otm.client.render.FlatRectangleIcon
import ru.dbotthepony.mc.otm.client.render.IGUIRenderable
import ru.dbotthepony.mc.otm.client.render.ItemStackIcon
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
import ru.dbotthepony.mc.otm.client.screen.panels.DockResizeMode
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.BooleanButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.ButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.ScrollableCanvasPanel
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.map
import ru.dbotthepony.mc.otm.core.util.CreativeMenuItemComparator
import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu

class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) : MatteryScreen<PainterMenu>(menu, inventory, title) {
	private inner class Bar(parent: EditablePanel<*>, val dye: DyeColor?) : EditablePanel<PainterScreen>(this@PainterScreen, parent, width = 5f) {
		init {
			dock = Dock.RIGHT
			dockLeft = 1f

			if (dye == null)
				tooltips.add(TranslatableComponent("block.minecraft.water"))
			else
				tooltips.add(TranslatableComponent("item.minecraft.${dye.getName() ?: "water"}_dye"))

			tooltips.add(TextComponent(""))
			tooltips.add(TextComponent(""))
		}

		override fun innerRender(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
			graphics.renderRect(0f, 0f, width, height, color = RGBAColor.DARK_GRAY)

			val color = RGBAColor.bgr(dye?.textColor ?: DyeColor.LIGHT_BLUE.textColor)

			graphics.renderCheckerboard(0f, 0f, width, height, color = color.copy(alpha = 0.25f))

			val multiplier = menu.dyeStoredDirect[dye]!!.toFloat() / (if (dye == null) PainterBlockEntity.MAX_WATER_STORAGE.toFloat() else PainterBlockEntity.MAX_STORAGE.toFloat())
			graphics.renderRect(0f, height * (1f - multiplier), width, height * multiplier, color = color)

			tooltips[tooltips.size - 1] = TextComponent("${menu.dyeStoredDirect[dye]} (${(multiplier * 100f).toInt()}%)")
		}
	}

	override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
		val frame = FramePanel(this, 244f, 120f, title)

		val strip = EditablePanel(this, frame, width = AbstractSlotPanel.SIZE)
		strip.dock = Dock.LEFT
		strip.dockRight = 4f

		SlotPanel(this, strip, menu.inputSlot).also {
			it.dock = Dock.TOP
			it.dockTop = 4f
		}

		EditablePanel(this, frame, width = 6f * (DyeColor.entries.size / 2f + 1f)).also {
			it.dock = Dock.RIGHT
			it.dockLeft = 4f

			Bar(it, null).childrenOrder = -1000

			EditablePanel(this, it, height = 46f).also {
				it.dock = Dock.TOP

				for (i in 0 until DyeColor.entries.size / 2) {
					Bar(it, DyeColor.entries[i])
				}
			}

			EditablePanel(this, it, height = 46f).also {
				it.dock = Dock.BOTTOM

				for (i in DyeColor.entries.size / 2 until DyeColor.entries.size) {
					Bar(it, DyeColor.entries[i])
				}
			}
		}

		SlotPanel(this, strip, menu.outputSlot).also {
			it.dock = Dock.BOTTOM
			it.dockBottom = 4f
		}

		SlotPanel(this, strip, menu.dyeSlot).also {
			it.dock = Dock.FILL
			it.dockResize = DockResizeMode.NONE
			it.slotBackgroundEmpty =
				ItemStackIcon(ItemStack(BuiltInRegistries.ITEM.getOrCreateTag(Tags.Items.DYES).getRandomElement(menu.random).map { it.value() }.orElse(Items.AIR)), 16f, 16f)
				.fixed()
				.composeBefore(FlatRectangleIcon(16f, 16f, RGBAColor.rgb(0x8b8b8b).copy(alpha = 0.6f)))
				.fixed()
		}

		val column = EditablePanel(this, frame)
		column.dock = Dock.FILL

		val bulk = BooleanButtonPanel.Checkbox(this, column, menu.isBulk, TranslatableComponent("otm.gui.painter.is_bulk"))
		bulk.dock = Dock.BOTTOM
		bulk.tooltips.add(TranslatableComponent("otm.gui.painter.is_bulk.desc"))
		bulk.tooltips.add(TranslatableComponent("otm.gui.painter.is_bulk.desc2").withStyle(ChatFormatting.GRAY))
		bulk.dockBottom = 4f

		val canvas = ScrollableCanvasPanel(this, column)
		canvas.dock = Dock.FILL
		canvas.dockPaddingBottom = 4f

		val buttons = ArrayList<ButtonPanel<PainterScreen>>()

		menu.listeners.addListener(Runnable {
			if (frame.isRemoved) return@Runnable
			buttons.forEach { it.remove() }
			buttons.clear()

			val recipes = menu.possibleRecipes
				.filter { !it.value.ingredients.isEmpty() }
				.sortedWith(CreativeMenuItemComparator.map { it.value.getOutput(menu.inputContainer).item })
				.plus(
					menu.possibleRecipes
						.filter { it.value.ingredients.isEmpty() }
						.sortedBy { it.id }
				)

			for (recipe in recipes) {
				val recipeOutput = recipe.value.getOutput(menu.inputContainer)

				object : ButtonPanel<PainterScreen>(this@PainterScreen, canvas.canvas, width = 18f, height = 18f) {
					init {
						buttons.add(this)
						dockRight = 1f
						dockBottom = 1f
					}

					override val icon: IGUIRenderable = ItemStackIcon(recipeOutput, 14f, 14f).fixed()

					override var isDisabled: Boolean
						get() = !recipe.value.canCraft(menu.dyeStoredDirect)
						set(value) {}

					override fun innerRenderTooltips(graphics: MGUIGraphics, mouseX: Float, mouseY: Float, partialTick: Float): Boolean {
						val list = getTooltipFromItem(minecraft!!, recipeOutput)

						recipe.value.dyes.forEach {
							val (dye, amount) = it

							if (dye == null) {
								if (amount == 1)
									list.add(TranslatableComponent("otm.gui.needs", TranslatableComponent("block.minecraft.water")))
								else if (amount > 1)
									list.add(TranslatableComponent("otm.gui.needs_x", TranslatableComponent("block.minecraft.water"), amount))
							} else {
								if (amount == 1)
									list.add(TranslatableComponent("otm.gui.needs", TranslatableComponent("item.minecraft.${dye.getName() ?: "water"}_dye")))
								else if (amount > 1)
									list.add(TranslatableComponent("otm.gui.needs_x", TranslatableComponent("item.minecraft.${dye.getName() ?: "water"}_dye"), amount))
							}
						}

						if (minecraft?.options?.advancedItemTooltips == true) {
							list.add(TextComponent(recipe.id.toString()).withStyle(ChatFormatting.DARK_GRAY))
						}

						graphics.renderComponentTooltip(font, list, mouseX.toInt(), mouseY.toInt())
						return true
					}

					override fun onClick(mouseButton: Int) {
						menu.selectRecipe.accept(recipe.id)
					}
				}
			}
		})

		DeviceControls(this, frame, itemConfig = menu.itemConfig)

		return frame
	}
}
