package ru.dbotthepony.mc.otm.item.matter

import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraft.world.entity.SlotAccess
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.ClickAction
import net.minecraft.world.inventory.Slot
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.config.ItemsConfig
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.matter.IMatterItem
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.matter.IMatterValue
import ru.dbotthepony.mc.otm.matter.MatterValue

class MatterDustItem : Item(Properties().stacksTo(64)), IMatterItem {
	private fun matter(stack: ItemStack): Decimal {
		return stack.tag?.get("matter")?.let { return@let Decimal.deserializeNBT(it) } ?: return Decimal.ZERO
	}

	private fun matter(stack: ItemStack, matter: Decimal) {
		stack.orCreateTag["matter"] = matter.serializeNBT()
	}

	override fun getMatterValue(stack: ItemStack): IMatterValue? {
		val value = stack.tag?.get("matter") ?: return null
		return MatterValue(Decimal.deserializeNBT(value), 1.0)
	}

	override fun canDecompose(stack: ItemStack) = false

	override fun appendHoverText(
		p_41421_: ItemStack,
		p_41422_: Level?,
		p_41423_: MutableList<Component>,
		p_41424_: TooltipFlag
	) {
		super.appendHoverText(p_41421_, p_41422_, p_41423_, p_41424_)
		val matter = this.getMatterValue(p_41421_)

		if (matter == null) {
			p_41423_.add(DESC)
		}

		p_41423_.add(DESC2)

		if (matter != null) {
			p_41423_.add(DESC3)
		}
	}

	fun addMatterValue(stack: ItemStack, matter: Decimal, simulate: Boolean): Decimal {
		if (stack.count != 1)
			return Decimal.ZERO

		val matterThis = matter(stack)

		if (matterThis >= ItemsConfig.MATTER_DUST_CAPACITY && matter.isPositive)
			return Decimal.ZERO

		val newMatter = (matterThis + matter).coerceAtMost(ItemsConfig.MATTER_DUST_CAPACITY)
		val diff = newMatter - matterThis

		if (!simulate)
			matter(stack, newMatter)

		return diff
	}

	fun isFull(stack: ItemStack): Boolean {
		return matter(stack) >= ItemsConfig.MATTER_DUST_CAPACITY
	}

	override fun overrideStackedOnOther(
		pStack: ItemStack,
		pSlot: Slot,
		pAction: ClickAction,
		pPlayer: Player
	): Boolean {
		if (pStack.isEmpty || pStack.count > 1)
			return super.overrideStackedOnOther(pStack, pSlot, pAction, pPlayer)

		if (pAction == ClickAction.SECONDARY && pSlot.allowModification(pPlayer)) {
			if (!pSlot.hasItem()) {
				val matterHalf = getMatterValue(pStack)?.matter?.div(2) ?: return true

				val halfStack = pStack.copyWithCount(1)
				matter(halfStack, -addMatterValue(pStack, -matterHalf, pPlayer.level().isClientSide()))
				pSlot.set(halfStack)

				if (getMatterValue(pStack)?.matter!! <= Decimal.ZERO) {
					pStack.shrink(1)
				}

				return true
			}
		}

		return super.overrideStackedOnOther(pStack, pSlot, pAction, pPlayer)
	}

	override fun overrideOtherStackedOnMe(
		pStack: ItemStack,
		pOther: ItemStack,
		pSlot: Slot,
		pAction: ClickAction,
		pPlayer: Player,
		pAccess: SlotAccess
	): Boolean {
		if (pStack.isEmpty || pStack.count > 1)
			return super.overrideStackedOnOther(pStack, pSlot, pAction, pPlayer)

		if (pAction == ClickAction.SECONDARY && pSlot.allowModification(pPlayer)) {
			if (pOther.isEmpty) {
				val matterHalf = getMatterValue(pStack)?.matter?.div(2) ?: return true

				val halfStack = pStack.copyWithCount(1)
				matter(halfStack, -addMatterValue(pStack, -matterHalf, pPlayer.level().isClientSide()))
				pAccess.set(halfStack)

				return true
			} else if (pOther.item is MatterDustItem && pOther.count == 1) {
				val matterOther = getMatterValue(pOther)?.matter ?: return true
				val diff = addMatterValue(pStack, matterOther, pPlayer.level().isClientSide())

				if (matterOther - diff <= Decimal.ZERO) {
					pOther.shrink(1)
				} else {
					matter(pStack, matterOther - diff)
				}

				return true
			}
		}

		return super.overrideOtherStackedOnMe(pStack, pOther, pSlot, pAction, pPlayer, pAccess)
	}

	companion object {
		private val DESC = TranslatableComponent("item.overdrive_that_matters.matter_dust.desc").withStyle(ChatFormatting.DARK_GRAY)
		private val DESC2 = TranslatableComponent("item.overdrive_that_matters.matter_dust.desc2").withStyle(ChatFormatting.GRAY)
		private val DESC3 = TranslatableComponent("item.overdrive_that_matters.matter_dust.desc3").withStyle(ChatFormatting.DARK_GRAY)
	}
}
