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

import it.unimi.dsi.fastutil.ints.IntArrayList
import net.minecraft.ChatFormatting
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.screens.Screen
import net.minecraft.network.chat.Component
import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage
import ru.dbotthepony.mc.otm.capability.energy.ProfiledEnergyStorage
import ru.dbotthepony.mc.otm.client.ShiftPressedCond
import ru.dbotthepony.mc.otm.client.isShiftDown
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.stream
import ru.dbotthepony.mc.otm.core.util.formatPower
import ru.dbotthepony.mc.otm.core.util.formatPowerLevel
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget

open class PowerGaugePanel<out S : Screen>(
	screen: S,
	parent: EditablePanel<*>? = null,
	val widget: LevelGaugeWidget,
	x: Float = 0f,
	y: Float = 0f,
	width: Float = GAUGE_BACKGROUND.width,
	height: Float = GAUGE_BACKGROUND.height
) : EditablePanel<S>(screen, parent, x, y, width, height) {
	init {
		scissor = true
	}

	protected open fun makeTooltip(): MutableList<Component> {
		return mutableListOf(
			TranslatableComponent("otm.gui.power.percentage_level", String.format("%.2f", widget.percentage * 100.0)),
			formatPowerLevel(widget.level, widget.maxLevel, formatAsReadable = ShiftPressedCond)
		)
	}

	override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
		val height = this.height * widget.percentage

		if (width >= 18f) {
			GAUGE_BACKGROUND_WIDE.render(graphics, width = width, height = this.height)
			GAUGE_FOREGROUND_WIDE.renderPartial(
				graphics,
				y = this.height - height,
				height = height,
				width = width,
				winding = UVWindingOrder.U0_V1_U1_V0)
		} else {
			GAUGE_BACKGROUND.render(graphics, width = width, height = this.height)
			GAUGE_FOREGROUND.renderPartial(
				graphics,
				y = this.height - height,
				height = height,
				width = width,
				winding = UVWindingOrder.U0_V1_U1_V0)
		}
	}

	override fun innerRenderTooltips(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float): Boolean {
		if (isHovered) {
			graphics.renderComponentTooltip(font, makeTooltip(), mouseX.toInt(), mouseY.toInt())
			return true
		}

		return false
	}

	companion object {
		val GAUGE_BACKGROUND = WidgetLocation.VERTICAL_GAUGES.sprite(x = 36f, width = 9f)
		val GAUGE_FOREGROUND = WidgetLocation.VERTICAL_GAUGES.sprite(x = 45f, width = 9f)

		val GAUGE_BACKGROUND_WIDE = WidgetLocation.VERTICAL_GAUGES.sprite(x = 54f, width = 18f)
		val GAUGE_FOREGROUND_WIDE = WidgetLocation.VERTICAL_GAUGES.sprite(x = 72f, width = 18f)
	}
}

/**
 * Shortcut to [PowerGaugePanel] with doubled width
 */
@Suppress("FunctionName")
fun <S : Screen> WidePowerGaugePanel(
	screen: S,
	parent: EditablePanel<*>? = null,
	widget: LevelGaugeWidget,
	x: Float = 0f,
	y: Float = 0f,
	width: Float = 18f,
	height: Float = 48f
) = PowerGaugePanel(screen, parent, widget, x, y, width, height)

private fun formatLevel(a: Decimal, b: Decimal): Component {
	val diff = a - b

	val fa = a.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_GREEN)
	val fb = b.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_RED)

	if (diff.isZero) {
		return TranslatableComponent("otm.gui.diff", diff.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.GRAY), fa, fb)
	} else if (diff.isPositive) {
		return TranslatableComponent("otm.gui.diff", diff.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_GREEN), fa, fb)
	} else {
		return TranslatableComponent("otm.gui.diff", (-diff).formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_RED), fa, fb)
	}
}

open class ProfiledPowerGaugePanel<out S : Screen>(
	screen: S,
	parent: EditablePanel<*>? = null,
	val profiledWidget: ProfiledLevelGaugeWidget<*>,
	x: Float = 0f,
	y: Float = 0f,
	width: Float = GAUGE_BACKGROUND.width,
	height: Float = GAUGE_BACKGROUND.height
) : PowerGaugePanel<S>(screen, parent, profiledWidget.gauge, x, y, width, height) {
	override fun makeTooltip(): MutableList<Component> {
		return super.makeTooltip().also {
			it.add(TextComponent(""))

			if (minecraft.window.isShiftDown) {
				it.add(formatLevel(profiledWidget.lastTickReceive, profiledWidget.lastTickTransfer))
				it.add(TextComponent("---"))
			}

			it.add(formatLevel(
				profiledWidget.weightedReceive,
				profiledWidget.weightedTransfer,
			))

			if (minecraft.window.isShiftDown && minecraft.options.advancedItemTooltips) {
				it.add(TextComponent("---"))
				val values = IntArrayList()

				values.addAll(profiledWidget.tick downTo 0)
				values.addAll(AbstractProfiledStorage.HISTORY_SIZE - 1 downTo profiledWidget.tick + 1)

				for (i in values.intIterator()) {
					it.add(formatLevel(profiledWidget.historyReceive[i].value, profiledWidget.historyTransfer[i].value))
				}
			}
		}
	}
}

/**
 * Shortcut to [ProfiledPowerGaugePanel] with doubled width
 */
@Suppress("FunctionName")
fun <S : Screen> WideProfiledPowerGaugePanel(
	screen: S,
	parent: EditablePanel<*>? = null,
	widget: ProfiledLevelGaugeWidget<*>,
	x: Float = 0f,
	y: Float = 0f,
	width: Float = 18f,
	height: Float = 48f
) = ProfiledPowerGaugePanel(screen, parent, widget, x, y, width, height)
