package net.minecraft.world.entity.projectile;

import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.network.protocol.Packet;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.level.ClipContext;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec3;
import net.minecraft.util.Mth;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Entity;

public abstract class AbstractHurtingProjectile extends Entity {
    public LivingEntity owner;
    private int life;
    private int flightTime;
    public double xPower;
    public double yPower;
    public double zPower;
    
    protected AbstractHurtingProjectile(final EntityType<? extends AbstractHurtingProjectile> aku, final Level bjw) {
        super(aku, bjw);
    }
    
    public AbstractHurtingProjectile(final EntityType<? extends AbstractHurtingProjectile> aku, final double double2, final double double3, final double double4, final double double5, final double double6, final double double7, final Level bjw) {
        this(aku, bjw);
        this.moveTo(double2, double3, double4, this.yRot, this.xRot);
        this.setPos(double2, double3, double4);
        final double double8 = Mth.sqrt(double5 * double5 + double6 * double6 + double7 * double7);
        this.xPower = double5 / double8 * 0.1;
        this.yPower = double6 / double8 * 0.1;
        this.zPower = double7 / double8 * 0.1;
    }
    
    public AbstractHurtingProjectile(final EntityType<? extends AbstractHurtingProjectile> aku, final LivingEntity akz, double double3, double double4, double double5, final Level bjw) {
        this(aku, bjw);
        this.owner = akz;
        this.moveTo(akz.getX(), akz.getY(), akz.getZ(), akz.yRot, akz.xRot);
        this.reapplyPosition();
        this.setDeltaMovement(Vec3.ZERO);
        double3 += this.random.nextGaussian() * 0.4;
        double4 += this.random.nextGaussian() * 0.4;
        double5 += this.random.nextGaussian() * 0.4;
        final double double6 = Mth.sqrt(double3 * double3 + double4 * double4 + double5 * double5);
        this.xPower = double3 / double6 * 0.1;
        this.yPower = double4 / double6 * 0.1;
        this.zPower = double5 / double6 * 0.1;
    }
    
    @Override
    protected void defineSynchedData() {
    }
    
    @Override
    public boolean shouldRenderAtSqrDistance(final double double1) {
        double double2 = this.getBoundingBox().getSize() * 4.0;
        if (Double.isNaN(double2)) {
            double2 = 4.0;
        }
        double2 *= 64.0;
        return double1 < double2 * double2;
    }
    
    @Override
    public void tick() {
        if (!this.level.isClientSide && ((this.owner != null && this.owner.removed) || !this.level.hasChunkAt(new BlockPos(this)))) {
            this.remove();
            return;
        }
        super.tick();
        if (this.shouldBurn()) {
            this.setSecondsOnFire(1);
        }
        ++this.flightTime;
        final HitResult cvi2 = ProjectileUtil.forwardsRaycast(this, true, this.flightTime >= 25, this.owner, ClipContext.Block.COLLIDER);
        if (cvi2.getType() != HitResult.Type.MISS) {
            this.onHit(cvi2);
        }
        final Vec3 cvl3 = this.getDeltaMovement();
        final double double4 = this.getX() + cvl3.x;
        final double double5 = this.getY() + cvl3.y;
        final double double6 = this.getZ() + cvl3.z;
        ProjectileUtil.rotateTowardsMovement(this, 0.2f);
        float float10 = this.getInertia();
        if (this.isInWater()) {
            for (int integer11 = 0; integer11 < 4; ++integer11) {
                final float float11 = 0.25f;
                this.level.addParticle(ParticleTypes.BUBBLE, double4 - cvl3.x * 0.25, double5 - cvl3.y * 0.25, double6 - cvl3.z * 0.25, cvl3.x, cvl3.y, cvl3.z);
            }
            float10 = 0.8f;
        }
        this.setDeltaMovement(cvl3.add(this.xPower, this.yPower, this.zPower).scale(float10));
        this.level.addParticle(this.getTrailParticle(), double4, double5 + 0.5, double6, 0.0, 0.0, 0.0);
        this.setPos(double4, double5, double6);
    }
    
    protected boolean shouldBurn() {
        return true;
    }
    
    protected ParticleOptions getTrailParticle() {
        return ParticleTypes.SMOKE;
    }
    
    protected float getInertia() {
        return 0.95f;
    }
    
    protected void onHit(final HitResult cvi) {
        final HitResult.Type a3 = cvi.getType();
        if (a3 == HitResult.Type.BLOCK) {
            final BlockHitResult cvg4 = (BlockHitResult)cvi;
            final BlockState byj5 = this.level.getBlockState(cvg4.getBlockPos());
            byj5.onProjectileHit(this.level, byj5, cvg4, this);
        }
    }
    
    public void addAdditionalSaveData(final CompoundTag jt) {
        final Vec3 cvl3 = this.getDeltaMovement();
        jt.put("direction", this.newDoubleList(cvl3.x, cvl3.y, cvl3.z));
        jt.put("power", this.newDoubleList(this.xPower, this.yPower, this.zPower));
        jt.putInt("life", this.life);
    }
    
    public void readAdditionalSaveData(final CompoundTag jt) {
        if (jt.contains("power", 9)) {
            final ListTag jz3 = jt.getList("power", 6);
            if (jz3.size() == 3) {
                this.xPower = jz3.getDouble(0);
                this.yPower = jz3.getDouble(1);
                this.zPower = jz3.getDouble(2);
            }
        }
        this.life = jt.getInt("life");
        if (jt.contains("direction", 9) && jt.getList("direction", 6).size() == 3) {
            final ListTag jz3 = jt.getList("direction", 6);
            this.setDeltaMovement(jz3.getDouble(0), jz3.getDouble(1), jz3.getDouble(2));
        }
        else {
            this.remove();
        }
    }
    
    @Override
    public boolean isPickable() {
        return true;
    }
    
    @Override
    public float getPickRadius() {
        return 1.0f;
    }
    
    @Override
    public boolean hurt(final DamageSource ajz, final float float2) {
        if (this.isInvulnerableTo(ajz)) {
            return false;
        }
        this.markHurt();
        if (ajz.getEntity() != null) {
            final Vec3 cvl4 = ajz.getEntity().getLookAngle();
            this.setDeltaMovement(cvl4);
            this.xPower = cvl4.x * 0.1;
            this.yPower = cvl4.y * 0.1;
            this.zPower = cvl4.z * 0.1;
            if (ajz.getEntity() instanceof LivingEntity) {
                this.owner = (LivingEntity)ajz.getEntity();
            }
            return true;
        }
        return false;
    }
    
    @Override
    public float getBrightness() {
        return 1.0f;
    }
    
    @Override
    public Packet<?> getAddEntityPacket() {
        final int integer2 = (this.owner == null) ? 0 : this.owner.getId();
        return new ClientboundAddEntityPacket(this.getId(), this.getUUID(), this.getX(), this.getY(), this.getZ(), this.xRot, this.yRot, this.getType(), integer2, new Vec3(this.xPower, this.yPower, this.zPower));
    }
}
