package ru.dbotthepony.mc.otm.entity

import net.minecraft.network.syncher.EntityDataAccessor
import net.minecraft.network.syncher.EntityDataSerializers
import net.minecraft.network.syncher.SynchedEntityData
import net.minecraft.resources.ResourceKey
import net.minecraft.core.registries.Registries
import ru.dbotthepony.mc.otm.core.ResourceLocation
import net.minecraft.world.level.storage.loot.LootTable
import net.minecraft.sounds.SoundEvent
import net.minecraft.sounds.SoundEvents
import net.minecraft.world.entity.AnimationState
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.EntityType
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.attributes.AttributeSupplier
import net.minecraft.world.entity.ai.attributes.Attributes
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal
import net.minecraft.world.entity.ai.goal.MeleeAttackGoal
import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal
import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal
import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal
import net.minecraft.world.entity.ai.navigation.GroundPathNavigation
import net.minecraft.world.entity.ai.navigation.PathNavigation
import net.minecraft.world.entity.monster.AbstractIllager
import net.minecraft.world.entity.monster.AbstractSkeleton
import net.minecraft.world.entity.monster.Monster
import net.minecraft.world.entity.monster.Zombie
import net.minecraft.world.entity.npc.Villager
import net.minecraft.world.entity.player.Player
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.registry.game.MSoundEvents


class Loader(type: EntityType<Loader>, level: Level) : Monster(type, level) {

	val idleState = AnimationState()
	var attackAnimationState = AnimationState()
	var attackAnimationTick = 0

	companion object {
		fun createAttributes() : AttributeSupplier.Builder {
			return createMonsterAttributes()
				.add(Attributes.MAX_HEALTH, 60.0)
				.add(Attributes.MOVEMENT_SPEED, 0.3)
				.add(Attributes.ATTACK_DAMAGE, 5.0)
				.add(Attributes.KNOCKBACK_RESISTANCE, 0.7)
		}

		private val DATA_ATTACKING: EntityDataAccessor<Boolean> =
			SynchedEntityData.defineId(Loader::class.java, EntityDataSerializers.BOOLEAN)
	}

	override fun defineSynchedData(builder: SynchedEntityData.Builder) {
		super.defineSynchedData(builder)
		builder.define(DATA_ATTACKING, false)
	}
	var isAttacking: Boolean
		get() = this.entityData.get(DATA_ATTACKING)
		set(value) {
			this.entityData.set(DATA_ATTACKING, value)
		}

	//https://nc.dbotthepony.ru/s/qqKdbQEYy74KyGM

	init {
		idleState.start(tickCount)
	}

	override fun registerGoals() {
		goalSelector.addGoal(8, RandomLookAroundGoal(this))
		goalSelector.addGoal(7, WaterAvoidingRandomStrollGoal(this, 0.8))
		goalSelector.addGoal(8, LookAtPlayerGoal(this, Player::class.java, 8f))
		goalSelector.addGoal(3, NearestAttackableTargetGoal(this, LivingEntity::class.java, 10, true, true) { entity ->
				entity is Player ||
				entity is Villager ||
				entity is AbstractIllager ||
				entity is Zombie ||
				entity is AbstractSkeleton
		})

		goalSelector.addGoal(2, MeleeAttackGoal(this, 1.0, true))

		targetSelector.addGoal(1, HurtByTargetGoal(this))
	}

	override fun handleEntityEvent(id: Byte) {
		if (id.toInt() == 4) {
			this.attackAnimationTick = 7 // Attack animation lasts 10 ticks
		} else {
			super.handleEntityEvent(id)
		}
	}

	override fun doHurtTarget(target: Entity): Boolean {
		level().broadcastEntityEvent(this, 4.toByte())
		val success = super.doHurtTarget(target)
		if (success) {
			this.playSound(SoundEvents.IRON_GOLEM_ATTACK, 1.0f, 1.0f)
			//THIS IS FUCKING RETARDED
			//fuck everything

			level().broadcastEntityEvent(this, 4.toByte())
			idleState.stop()
			idleState.start(tickCount)


			val dirx = target.x - this.x
			val dirz = target.z - this.z
			val dist = Math.sqrt(dirx * dirx + dirx * dirz)

			target.push(dirx / dist * 0.6, 0.3, dirz / dist * 0.6)
		}
		return success
	}

	override fun getDefaultLootTable(): ResourceKey<LootTable> {
		return ResourceKey.create(Registries.LOOT_TABLE,
			ResourceLocation(OverdriveThatMatters.MOD_ID, "entities/loader"))
	}

	override fun aiStep() {
		super.aiStep()

		if (attackAnimationTick > 0) {
			attackAnimationTick--
			if (attackAnimationTick == 0) {
				isAttacking = false
			}
		}
	}
	override fun getAmbientSound(): SoundEvent {
		return  MSoundEvents.LOADER_AMBIENT
	}

	override fun getHurtSound(damageSource: net.minecraft.world.damagesource.DamageSource): SoundEvent {
		return SoundEvents.IRON_GOLEM_HURT
	}

	override fun getDeathSound(): SoundEvent {
		return SoundEvents.IRON_GOLEM_DEATH
	}

	override fun playStepSound(pos: net.minecraft.core.BlockPos, blockState: net.minecraft.world.level.block.state.BlockState) {
		this.playSound(SoundEvents.IRON_GOLEM_STEP, 1.0f, 1.0f)
	}

	override fun createNavigation(level: Level): PathNavigation = GroundPathNavigation(this, level)
}
