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

import net.minecraft.world.inventory.Slot
import ru.dbotthepony.mc.otm.SystemTime
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.util.BackgroundPanel
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.client.screen.panels.ISlotPanel

open class FoldableSlotPanel<out S : MatteryScreen<*>, out T : Slot> @JvmOverloads constructor(
	screen: S,
	parent: EditablePanel<*>?,
	val mainSlot: SlotPanel<S, T>,
	val extraSlots: Collection<EditablePanel<S>>,
	x: Float = 0f,
	y: Float = 0f,
	width: Float = AbstractSlotPanel.SIZE,
	height: Float = AbstractSlotPanel.SIZE,
) : EditablePanel<S>(screen, parent, x, y, width, height), ISlotPanel<T> {
	init {
		mainSlot.parent = this
		mainSlot.dock = Dock.FILL
	}

	open inner class HoverPanel : BackgroundPanel<S>(
		screen,
		null,
		this@FoldableSlotPanel.absoluteX,
		this@FoldableSlotPanel.absoluteY,
		width = extraSlots.stream().mapToDouble { (it.width + it.dockMargin.right + it.dockMargin.left).toDouble() }.sum().toFloat() + mainSlot.width + mainSlot.dockMargin.left + mainSlot.dockMargin.right,
		height = extraSlots.stream().mapToDouble { (it.height + it.dockMargin.top + it.dockMargin.bottom).toDouble() }.max().orElse(0.0).toFloat().coerceAtLeast(mainSlot.height + mainSlot.dockMargin.top + mainSlot.dockMargin.bottom),
	) {
		init {
			x -= dockPadding.left
			y -= dockPadding.top

			width += dockPadding.left + dockPadding.right
			height += dockPadding.top + dockPadding.bottom

			mainSlot.parent = this
			mainSlot.dock = Dock.LEFT

			for (slot in extraSlots) {
				slot.parent = this
				slot.dock = Dock.LEFT
			}

			screen.addPanel(this)
		}

		override fun beforeRemoved() {
			mainSlot.parent = this@FoldableSlotPanel
			mainSlot.dock = Dock.FILL

			for (slot in extraSlots) {
				slot.parent = null
			}

			this@FoldableSlotPanel.hoverPanel = null
		}

		override fun onUnHovered() {
			remove()
		}

		override fun tickInner() {
			super.tickInner()

			x = this@FoldableSlotPanel.absoluteX - dockPadding.left
			y = this@FoldableSlotPanel.absoluteY - dockPadding.top
		}
	}

	override val slot: T
		get() = mainSlot.slot

	var hoveringSince: SystemTime? = null
		protected set
	var hoverPanel: HoverPanel? = null
		protected set

	override fun onHovered() {
		hoveringSince = SystemTime()
	}

	override fun onUnHovered() {
		hoveringSince = null
	}

	override fun beforeRemoved() {
		hoverPanel?.remove()
	}

	override fun tickInner() {
		super.tickInner()

		val hoveringSince = hoveringSince

		if (hoveringSince != null && hoveringSince.nanos >= MAX_HOVER_TIME && hoverPanel == null && extraSlots.isNotEmpty()) {
			hoverPanel = HoverPanel()
		}
	}

	companion object {
		const val MAX_HOVER_TIME = 1_000_000_000
	}
}
