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

import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import java.math.BigDecimal
import java.util.function.BooleanSupplier

open class NetworkNumberInputPanel<out S : Screen> @JvmOverloads constructor(
	screen: S,
	parent: EditablePanel<*>?,
	val networkValue: () -> BigDecimal,
	val callback: (BigDecimal) -> Unit,
	val isAvailable: BooleanSupplier = BooleanSupplier { true },
	x: Float = 0f,
	y: Float = 0f,
	width: Float = 0f,
	height: Float = 20f,
	defaultText: Component = TextComponent("")
) : EditBoxPanel<S>(screen, parent, x, y, width, height, defaultText) {
	constructor(
		screen: S,
		parent: EditablePanel<*>?,
		widget: MatteryMenu.PlayerInput<BigDecimal>,
		networkValue: () -> BigDecimal,
		x: Float = 0f,
		y: Float = 0f,
		width: Float = 0f,
		height: Float = 20f,
		defaultText: Component = TextComponent("")
	) : this(
		screen = screen,
		parent = parent,
		callback = widget::input,
		isAvailable = { widget.allowSpectators || minecraft.player?.isSpectator != true },
		networkValue = networkValue,
		x = x,
		y = y,
		width = width,
		height = height,
		defaultText = defaultText,
	)

	protected var nextUpdateFromServer = 0L
	protected var inputStr = ""

	override fun mouseClickedInner(x: Double, y: Double, button: Int): Boolean {
		if (!isAvailable.asBoolean) {
			return true
		}

		return super.mouseClickedInner(x, y, button)
	}

	override fun tickInner() {
		super.tickInner()

		if (isFocusedThis) {
			if (!isAvailable.asBoolean) {
				killFocus()
				return
			}

			nextUpdateFromServer = System.currentTimeMillis() + 2000L
		}

		if (nextUpdateFromServer < System.currentTimeMillis()) {
			getOrCreateWidget().value = networkValue.invoke().toPlainString()
			inputStr = getOrCreateWidget().value
		} else if (isAvailable.asBoolean) {
			if (inputStr != getOrCreateWidget().value) {
				inputStr = getOrCreateWidget().value

				try {
					callback.invoke(BigDecimal(inputStr))
				} catch (_: Throwable) { }
			}
		}
	}
}
