package ru.dbotthepony.mc.otm.item.consumables

import net.minecraft.ChatFormatting
import net.minecraft.core.component.DataComponentMap
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.Style
import net.minecraft.tags.TagKey
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
import net.minecraft.world.InteractionResultHolder
import net.minecraft.world.entity.EntityType
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.OwnableEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.UseAnim
import net.minecraft.world.level.Level
import net.minecraft.world.level.gameevent.GameEvent
import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent.EntityInteract
import ru.dbotthepony.mc.otm.capability.matteryPlayer
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.core.damageType
import ru.dbotthepony.mc.otm.item.MatteryItem
import ru.dbotthepony.mc.otm.registry.MDamageTypes
import ru.dbotthepony.mc.otm.registry.MatteryDamageSource
import ru.dbotthepony.mc.otm.runIfClient

class NotNormalFood(
	val mimicking: () -> Item,
	val usableOn: TagKey<EntityType<*>>? = null,
	val usableOnOwned: TagKey<EntityType<*>>? = null
) : MatteryItem(Properties()) { // properties go unused because this item use properties aka components of mimicked item
	constructor(mimicking: () -> Item, tags: Pair<TagKey<EntityType<*>>, TagKey<EntityType<*>>>) : this(mimicking, tags.first, tags.second)

	init {
		tooltips.addDetailed(TranslatableComponent("otm.pill.suspicious_food.desc").withStyle(ChatFormatting.GRAY))
	}

	override fun components(): DataComponentMap {
		return mimicking().components()
	}

	override fun getDefaultMaxStackSize(): Int {
		return mimicking().defaultMaxStackSize
	}

	override fun getUseAnimation(stack: ItemStack): UseAnim {
		return mimicking().getUseAnimation(stack)
	}

	override fun getUseDuration(stack: ItemStack, entity: LivingEntity): Int {
		return mimicking().getUseDuration(stack, entity)
	}

	override fun use(level: Level, player: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
		return mimicking().use(level, player, hand)
	}

	override fun finishUsingItem(stack: ItemStack, level: Level, entity: LivingEntity): ItemStack {
		val copy = stack.copy()
		val result = mimicking().finishUsingItem(stack, level, entity)

		if (entity.matteryPlayer?.isAndroid != true) {
			entity.health = 1f
			val source = MatteryDamageSource(level.registryAccess().damageType(MDamageTypes.NOT_NORMAL_PILL), inflictor = copy)

			entity.invulnerableTime = 0
			entity.hurt(source, Float.MAX_VALUE)

			if (entity.isAlive)
				entity.die(source)
		}

		return result
	}

	override fun getDescription(): Component {
		if (runIfClient(false) { minecraft.window.isShiftDown }) {
			return TranslatableComponent("otm.pill.suspicious_food", mimicking().description)
		}

		return mimicking().getDescription()
	}

	override fun getName(stack: ItemStack): Component {
		if (runIfClient(false) { minecraft.window.isShiftDown }) {
			return TranslatableComponent("otm.pill.suspicious_food", mimicking().getName(stack))
		}

		return mimicking().getName(stack)
	}

	override fun getDescriptionId(): String {
		if (!runIfClient(false) { minecraft.window.isShiftDown })
			return mimicking().getDescriptionId()

		return super.getDescriptionId()
	}

	override fun getDescriptionId(stack: ItemStack): String {
		if (!runIfClient(false) { minecraft.window.isShiftDown })
			return mimicking().getDescriptionId(stack)

		return super.getDescriptionId(stack)
	}

	companion object {
		fun onInteract(event: EntityInteract) {
			val item = event.itemStack.item as? NotNormalFood ?: return
			val target = event.target as? LivingEntity ?: return

			if (
				item.usableOn != null && event.target.type.`is`(item.usableOn) ||
				item.usableOnOwned != null && event.target.type.`is`(item.usableOnOwned) && event.target is OwnableEntity && (event.target as OwnableEntity).ownerUUID == event.entity.uuid
			) {
				event.isCanceled = true
				val copy = event.itemStack.copy()

				if (!event.entity.hasInfiniteMaterials()) {
					event.itemStack.shrink(1)
				}

				event.cancellationResult = InteractionResult.sidedSuccess(target.level().isClientSide)
				target.gameEvent(GameEvent.EAT)

				if (!target.level().isClientSide) {
					target.health = 1f
					val source = MatteryDamageSource(target.level().registryAccess().damageType(MDamageTypes.NOT_NORMAL_PILL), inflictor = copy)

					target.invulnerableTime = 0
					target.hurt(source, Float.MAX_VALUE)

					if (target.isAlive)
						target.die(source)
				}
			}
		}
	}
}
