package ru.dbotthepony.mc.otm.entity

import net.minecraft.core.particles.ParticleTypes
import net.minecraft.world.entity.EntityType
import net.minecraft.world.entity.projectile.Projectile
import net.minecraft.world.entity.projectile.ProjectileUtil
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Blocks
import net.minecraft.world.level.block.LevelEvent
import net.minecraft.world.phys.BlockHitResult
import net.minecraft.world.phys.EntityHitResult
import net.minecraft.world.phys.HitResult
import net.minecraftforge.event.ForgeEventFactory
import ru.dbotthepony.mc.otm.core.damageType
import ru.dbotthepony.mc.otm.registry.MDamageTypes
import ru.dbotthepony.mc.otm.registry.MEntityTypes
import ru.dbotthepony.mc.otm.registry.MatteryDamageSource

class PlasmaProjectile(level: Level) : Projectile(MEntityTypes.PLASMA as EntityType<out Projectile>, level) {
	var inflictor: ItemStack? = null
	var damage = 6.0f
	var ttl = 200

	override fun defineSynchedData() {

	}

	override fun onHit(p_37260_: HitResult) {
		super.onHit(p_37260_)

		if (!level().isClientSide) {
			discard()
		}
	}

	override fun onHitEntity(p_37259_: EntityHitResult) {
		super.onHitEntity(p_37259_)

		if (!level().isClientSide) {
			p_37259_.entity.hurt(MatteryDamageSource(level().registryAccess().damageType(MDamageTypes.PLASMA), owner, inflictor), damage)
		}
	}

	override fun onHitBlock(p_37258_: BlockHitResult) {
		super.onHitBlock(p_37258_)
	}

	override fun tick() {
		if (--ttl <= 0) {
			discard()
			return
		}

		super.tick()

		val trace = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity)

		if (trace.type == HitResult.Type.BLOCK) {
			val pos = (trace as BlockHitResult).blockPos
			val state = level().getBlockState(pos)

			if (state.`is`(Blocks.NETHER_PORTAL) || state.`is`(Blocks.END_GATEWAY)) {
				onHitBlock(trace)

				// don't teleport plasma projectile
				if (!level().isClientSide)
					discard()

				return
			}
		}

		if (trace.type != HitResult.Type.MISS && !ForgeEventFactory.onProjectileImpact(this, trace)) {
			onHit(trace)
		}

		checkInsideBlocks()

		val x = x + deltaMovement.x
		val y = y + deltaMovement.y
		val z = z + deltaMovement.z

		if (isInWater) {
			// extinguish

			for (i in 0 .. 4) {
				level().addParticle(
					ParticleTypes.BUBBLE,
					x - deltaMovement.x * 0.25,
					y - deltaMovement.y * 0.25,
					z - deltaMovement.z * 0.25,
					deltaMovement.x,
					deltaMovement.y,
					deltaMovement.z,
				)
			}

			if (!level().isClientSide) {
				discard()
				level().levelEvent(LevelEvent.LAVA_FIZZ, blockPosition(), 0)
			}

			return
		}

		setPos(x, y, z)
	}

	companion object {

	}
}
