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

import net.minecraft.client.gui.screens.Screen
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel

class ScrollableCanvasPanel<out S : Screen>(
	screen: S,
	parent: EditablePanel<*>,
	x: Float = 0f,
	y: Float = 0f,
	width: Float = 40f,
	height: Float = 40f,
	slimScrollbar: Boolean = false
) : EditablePanel<S>(screen, parent, x, y, width, height) {
	val canvas = object : EditablePanel<S>(screen, this@ScrollableCanvasPanel) {
		init {
			dock = Dock.FILL
			dockRight = 1f
			scissor = true
		}

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

		override fun performLayout() {
			super.performLayout()

			var y = 0f
			var maxHeight = 0f
			var x = 0f

			for (child in visibleChildren.filter { it.dock == Dock.NONE }) {
				if (x > 0f && x + child.width > this.width) {
					y += maxHeight
					x = 0f
					maxHeight = 0f
				}

				child.x = child.dockLeft + x
				child.y = child.dockTop + y
				x += child.width + child.dockMargin.horizontal
				maxHeight = maxHeight.coerceAtLeast(child.height + child.dockMargin.vertical)
			}

			updateBounds()

			if (getMaxScroll(scrollbar) <= scrollbar.scroll) {
				scrollbar.scroll = getMaxScroll(scrollbar)
			}
		}
	}

	val scrollbar = AnalogScrollBarPanel(screen, this, maxScroll = ::getMaxScroll, smoothScrollCallback = ::onScrollUpdate, isSlim = slimScrollbar)

	init {
		scrollbar.dock = Dock.RIGHT
	}

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

	private fun getMaxScroll(it: AnalogScrollBarPanel<*>): Float {
		return (canvas.childrenRectHeight - canvas.height).coerceAtLeast(0f)
	}

	private fun onScrollUpdate(it: AnalogScrollBarPanel<*>, old: Float, new: Float) {
		this.canvas.yOffset = -new
	}
}
