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

import net.minecraft.ChatFormatting
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.network.chat.Component
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.client.render.RenderGravity
import ru.dbotthepony.mc.otm.client.render.draw
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.DiscreteScrollBarPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.GridPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.ScrollBarConstants
import ru.dbotthepony.mc.otm.client.screen.storage.ItemMonitorScreen
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.integerDivisionDown
import ru.dbotthepony.mc.otm.core.util.formatReadableNumber
import ru.dbotthepony.mc.otm.core.util.formatSiComponent
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView
import ru.dbotthepony.mc.otm.storage.StorageStack

open class NetworkedItemGridPanel<out S : MatteryScreen<*>>(
	screen: S,
	parent: EditablePanel<*>,
	val view: NetworkedItemView,
	x: Float = 0f,
	y: Float = 0f,
	width: Float = 40f,
	height: Float = 40f,
) : EditablePanel<S>(screen, parent, x, y, width, height) {
	constructor(
		screen: S,
		parent: EditablePanel<*>,
		view: NetworkedItemView,
		x: Float = 0f,
		y: Float = 0f,
		width: Int,
		height: Int
	) : this(screen, parent, view, x, y, width * AbstractSlotPanel.SIZE + ScrollBarConstants.WIDTH, height * AbstractSlotPanel.SIZE)

	private val slots = ArrayList<Slot>()

	val canvas = object : GridPanel<S>(screen, this@NetworkedItemGridPanel, 0f, 0f, 0f, 0f, 0, 0) {
		override fun performLayout() {
			super.performLayout()

			val count = columns * rows

			while (slots.size < count) {
				slots.add(Slot(slots.size))
			}

			while (slots.size > count) {
				slots.removeLast().remove()
			}
		}
	}

	val scrollbar = DiscreteScrollBarPanel(
		screen,
		this,
		{ integerDivisionDown(view.itemCount, canvas.columns) },
		{ _, _, _ -> }
	)

	inner class Slot(private val i: Int) : AbstractSlotPanel<S>(screen, canvas) {
		private val index get() = i + scrollbar.scroll * canvas.columns

		override val itemStack: ItemStack get() {
			return view.sortedView.getOrNull(index)?.stack?.toItemStack() ?: ItemStack.EMPTY
		}

		override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
			return scrollbar.mouseScrolledInner(x, y, scroll)
		}

		override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
			view.mouseClick(index, button)
			return true
		}

		override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
			renderSlotBackground(graphics, mouseX, mouseY, partialTick)
			val itemStack = view.sortedView.getOrNull(index)?.stack ?: StorageStack.ITEMS.empty
			renderRegular(graphics, itemStack.toItemStack(), "")

			if (!itemStack.isEmpty) {
				graphics.draw(font, itemStack.count.formatSiComponent(decimalPlaces = 1), x = width - 1f, y = height - 1f, gravity = RenderGravity.BOTTOM_RIGHT, scale = 0.75f, drawShadow = true)
			}
		}

		override fun getItemStackTooltip(stack: ItemStack): MutableList<Component> {
			return super.getItemStackTooltip(stack).also {
				it.add(TranslatableComponent("otm.gui.stored_amount", view.sortedView[index].stack.count.formatReadableNumber()).withStyle(ChatFormatting.DARK_GRAY))
			}
		}
	}

	init {
		canvas.dock = Dock.FILL
		scrollbar.dock = Dock.RIGHT
	}

	override fun performLayout() {
		super.performLayout()

		canvas.rows = (canvas.height / AbstractSlotPanel.SIZE).toInt()
		canvas.columns = (canvas.width / AbstractSlotPanel.SIZE).toInt()
	}
}
