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

import net.minecraft.ChatFormatting
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.player.Inventory
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.isShiftDown
import ru.dbotthepony.mc.otm.client.render.MatteryAtlas
import ru.dbotthepony.mc.otm.client.render.RenderGravity
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
import ru.dbotthepony.mc.otm.client.screen.panels.DockProperty
import ru.dbotthepony.mc.otm.client.screen.panels.DockResizeMode
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
import ru.dbotthepony.mc.otm.client.screen.panels.Label
import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeRectangleButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.makeDeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.input.TextInputPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.HorizontalStripPanel
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.util.getLevelFromXp
import ru.dbotthepony.mc.otm.core.util.getTotalXpRequiredForLevel
import ru.dbotthepony.mc.otm.core.util.getXpRequiredForLevelUp
import ru.dbotthepony.mc.otm.menu.tech.EssenceStorageMenu
import ru.dbotthepony.mc.otm.registry.MItems

class EssenceStorageScreen(menu: EssenceStorageMenu, inventory: Inventory, title: Component) : MatteryScreen<EssenceStorageMenu>(menu, title) {
	override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
		val frame = FramePanel.padded(this, width = DEFAULT_FRAME_WIDTH, height = 18f * 2f + 36f + 25f, title)

		frame.makeCloseButton()
		frame.onClose { onClose() }

		val inputs = HorizontalStripPanel(this, frame, height = 18f)
		inputs.dock = Dock.TOP
		inputs.dockMargin = DockProperty(bottom = 3f, top = 3f)

		SlotPanel(this, inputs, menu.capsuleSlot).also {
			it.dock = Dock.RIGHT
			it.tooltips.add(MItems.ESSENCE_CAPSULE.description.copy().withStyle(ChatFormatting.GRAY))
		}

		HorizontalStripPanel(this, frame, height = 18f).also {
			it.dock = Dock.TOP
			it.dockMargin = DockProperty(bottom = 3f)

			object : EditablePanel<EssenceStorageScreen>(this@EssenceStorageScreen, it, width = 108f, height = 15f) {
				init {
					dockResize = DockResizeMode.NONE
					dockMargin = DockProperty(bottom = 3f)
				}

				override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
					BAR_BACKGROUND.render(graphics, width = width, height = height)
					val level = getLevelFromXp(menu.experienceStored)
					val progress = (menu.experienceStored - getTotalXpRequiredForLevel(level)).toDouble() / getXpRequiredForLevelUp(level).toDouble()
					BAR_FOREGROUND.renderPartial(graphics, width = width * progress.toFloat(), height = height)
				}
			}

			SlotPanel(this, it, menu.servoSlot).also {
				it.dock = Dock.RIGHT
				it.tooltips.add(MItems.ESSENCE_SERVO.description.copy().withStyle(ChatFormatting.GRAY))
			}
		}

		object : Label<EssenceStorageScreen>(this@EssenceStorageScreen, frame, text = TextComponent("")) {
			init {
				dock = Dock.TOP
				dockMargin = DockProperty(bottom = 3f)
				align = RenderGravity.TOP_CENTER
			}

			override fun tickInner() {
				super.tickInner()

				if (minecraft?.window?.isShiftDown == true) {
					text = TranslatableComponent("otm.gui.experience", menu.experienceStored)
				} else {
					text = TranslatableComponent("otm.gui.experience_levels", getLevelFromXp(menu.experienceStored))
				}
			}
		}

		val outputs = HorizontalStripPanel(this, frame, width = 18f * 3 + 3f * 3, height = 18f)
		outputs.dock = Dock.TOP
		outputs.dockResize = DockResizeMode.NONE
		outputs.dockMargin = DockProperty(bottom = 3f)

		object : LargeRectangleButtonPanel<EssenceStorageScreen>(this@EssenceStorageScreen, inputs, skinElement = STORE_1) {
			init {
				dockRight = 3f
				tooltips.add(TranslatableComponent("otm.gui.experience.store", 1))
			}

			override fun onClick(mouseButton: Int) {
				menu.storeLevels.input(1)
			}

			override var isDisabled: Boolean
				get() = !menu.storeLevels.test(minecraft?.player)
				set(value) {}
		}

		object : LargeRectangleButtonPanel<EssenceStorageScreen>(this@EssenceStorageScreen, inputs, skinElement = STORE_10) {
			init {
				dockRight = 3f
				tooltips.add(TranslatableComponent("otm.gui.experience.store", 10))
			}

			override fun onClick(mouseButton: Int) {
				menu.storeLevels.input(10)
			}

			override var isDisabled: Boolean
				get() = !menu.storeLevels.test(minecraft?.player)
				set(value) {}
		}

		object : LargeRectangleButtonPanel<EssenceStorageScreen>(this@EssenceStorageScreen, inputs, skinElement = STORE_ALL) {
			init {
				dockRight = 3f
				tooltips.add(TranslatableComponent("otm.gui.experience.store_all"))
			}

			override fun onClick(mouseButton: Int) {
				menu.storeLevels.input((minecraft?.player?.experienceLevel ?: 0) + 1)
			}

			override var isDisabled: Boolean
				get() = !menu.storeLevels.test(minecraft?.player)
				set(value) {}
		}

		object : LargeRectangleButtonPanel<EssenceStorageScreen>(this@EssenceStorageScreen, outputs, skinElement = DISPENSE_1) {
			init {
				dockRight = 3f
				tooltips.add(TranslatableComponent("otm.gui.experience.dispense", 1))
			}

			override fun onClick(mouseButton: Int) {
				menu.dispenseLevels.input(1)
			}

			override var isDisabled: Boolean
				get() = !menu.dispenseLevels.test(minecraft?.player)
				set(value) {}
		}

		object : LargeRectangleButtonPanel<EssenceStorageScreen>(this@EssenceStorageScreen, outputs, skinElement = DISPENSE_10) {
			init {
				dockRight = 3f
				tooltips.add(TranslatableComponent("otm.gui.experience.dispense", 10))
			}

			override fun onClick(mouseButton: Int) {
				menu.dispenseLevels.input(10)
			}

			override var isDisabled: Boolean
				get() = !menu.dispenseLevels.test(minecraft?.player)
				set(value) {}
		}

		object : LargeRectangleButtonPanel<EssenceStorageScreen>(this@EssenceStorageScreen, outputs, skinElement = DISPENSE_ALL) {
			init {
				dockRight = 3f
				tooltips.add(TranslatableComponent("otm.gui.experience.dispense_all"))
			}

			override fun onClick(mouseButton: Int) {
				menu.dispenseLevels.input(getLevelFromXp(menu.experienceStored) + 1)
			}

			override var isDisabled: Boolean
				get() = !menu.dispenseLevels.test(minecraft?.player)
				set(value) {}
		}

		val customBar = HorizontalStripPanel(this, frame, height = 18f)
		customBar.dock = Dock.TOP

		object : LargeRectangleButtonPanel<EssenceStorageScreen>(this@EssenceStorageScreen, customBar, skinElement = STORE_CUSTOM) {
			init {
				tooltips.add(TranslatableComponent("otm.gui.experience.store", customDispense))
			}

			override fun onClick(mouseButton: Int) {
				menu.storeLevels.input(customDispense)
			}

			override var isDisabled: Boolean
				get() = !menu.storeLevels.test(minecraft?.player)
				set(value) {}
		}

		object : TextInputPanel<EssenceStorageScreen>(this@EssenceStorageScreen, customBar, width = 60f) {
			init {
				dockMargin = DockProperty(left = 3f, right = 3f)
				text = customDispense.toString()
			}

			override fun onTextChanged(old: String, new: String) {
				customDispense = (new.toIntOrNull() ?: 30).coerceAtLeast(1)
			}
		}

		object : LargeRectangleButtonPanel<EssenceStorageScreen>(this@EssenceStorageScreen, customBar, skinElement = DISPENSE_CUSTOM) {
			init {
				tooltips.add(TranslatableComponent("otm.gui.experience.dispense", customDispense))
			}

			override fun onClick(mouseButton: Int) {
				menu.dispenseLevels.input(customDispense)
			}

			override var isDisabled: Boolean
				get() = !menu.dispenseLevels.test(minecraft?.player)
				set(value) {}
		}

		object : LargeRectangleButtonPanel<EssenceStorageScreen>(this@EssenceStorageScreen, customBar, skinElement = SET_EXACT) {
			init {
				tooltips.add(TranslatableComponent("otm.gui.experience.set_exact", customDispense))
				dock = Dock.RIGHT
				dockMargin = DockProperty(right = 4f)
			}

			override fun onClick(mouseButton: Int) {
				val player = minecraft?.player ?: return

				if (player.experienceLevel == customDispense) {
					if (player.experienceProgress > 0f) {
						menu.storeLevels.input(1)
					}
				} else if (player.experienceLevel > customDispense) {
					menu.storeLevels.input(player.experienceLevel - customDispense)
				} else {
					menu.dispenseLevels.input(customDispense - player.experienceLevel)
				}
			}

			override var isDisabled: Boolean
				get() = !menu.dispenseLevels.test(minecraft?.player) && !menu.storeLevels.test(minecraft?.player)
				set(value) {}
		}

		makeDeviceControls(this, frame, redstoneConfig = menu.redstoneConfig, itemConfig = menu.itemConfig)

		return frame
	}

	companion object {
		private var customDispense = 30

		val ATLAS = MatteryAtlas(ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/essence_storage.png"), 108f, 66f)
		val STORE_1 = ATLAS.sprite(width = 18f, height = 18f)
		val STORE_10 = ATLAS.sprite(x = 18f, width = 18f, height = 18f)
		val STORE_ALL = ATLAS.sprite(x = 18f * 2, width = 18f, height = 18f)
		val DISPENSE_1 = ATLAS.sprite(x = 18f * 3, width = 18f, height = 18f)
		val DISPENSE_10 = ATLAS.sprite(x = 18f * 4, width = 18f, height = 18f)
		val DISPENSE_ALL = ATLAS.sprite(x = 18f * 5, width = 18f, height = 18f)
		val BAR_BACKGROUND = ATLAS.sprite(y = 18f, height = 15f)
		val BAR_FOREGROUND = ATLAS.sprite(y = 18f + 15f, height = 15f)

		val STORE_CUSTOM = ATLAS.sprite(width = 18f, height = 18f, y = 48f)
		val DISPENSE_CUSTOM = ATLAS.sprite(width = 18f, height = 18f, y = 48f, x = 18f)
		val SET_EXACT = ATLAS.sprite(width = 18f, height = 18f, y = 48f, x = 18f * 2f)
	}
}
