package ru.dbotthepony.mc.otm.triggers

import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.advancements.critereon.DamagePredicate
import net.minecraft.advancements.critereon.DamageSourcePredicate
import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.advancements.critereon.MinMaxBounds
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.entity.LivingEntity
import ru.dbotthepony.mc.otm.data.DamagePredicateCodec
import java.util.*

class HurtTrigger(id: ResourceLocation) : MCriterionTrigger<HurtTrigger.Instance>(id) {
	fun trigger(player: ServerPlayer, entity: LivingEntity, damage: Float, damageSource: DamageSource) {
		val context = EntityPredicate.createContext(player, entity)

		trigger(player) {
			it.predicate.map { it.matches(context) }.orElse(true) && it.damagePredicate.map { it.matches(player, damageSource, damage, damage, false) }.orElse(true)
		}
	}

	override val codec: Codec<Instance> = RecordCodecBuilder.create {
		it.group(
			predicateCodec.optionalFieldOf("predicate").forGetter(Instance::predicate),
			DamagePredicateCodec.optionalFieldOf("damagePredicate").forGetter(Instance::damagePredicate),
			playerPredicateCodec.forGetter(Instance::playerPredicate)
		).apply(it, ::Instance)
	}

	inner class Instance(
		val predicate: Optional<ContextAwarePredicate> = Optional.empty(),
		val damagePredicate: Optional<DamagePredicate> = Optional.of(DamagePredicate(
			MinMaxBounds.Doubles.atLeast(1.0),
			MinMaxBounds.Doubles.atLeast(1.0),
			EntityPredicate.ANY,
			null,
			DamageSourcePredicate.ANY
		)),
		player: Optional<ContextAwarePredicate> = Optional.empty()
	) : AbstractInstance(player)
}
