package net.minecraft.world.entity.projectile;

import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.core.BlockPos;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.global.LightningBolt;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.damagesource.DamageSource;
import javax.annotation.Nullable;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.network.syncher.EntityDataAccessor;

public class ThrownTrident extends AbstractArrow {
    private static final EntityDataAccessor<Byte> ID_LOYALTY;
    private static final EntityDataAccessor<Boolean> ID_FOIL;
    private ItemStack tridentItem;
    private boolean dealtDamage;
    public int clientSideReturnTridentTickCount;
    
    public ThrownTrident(final EntityType<? extends ThrownTrident> aku, final Level bjw) {
        super(aku, bjw);
        this.tridentItem = new ItemStack(Items.TRIDENT);
    }
    
    public ThrownTrident(final Level bjw, final LivingEntity akz, final ItemStack ben) {
        super(EntityType.TRIDENT, akz, bjw);
        this.tridentItem = new ItemStack(Items.TRIDENT);
        this.tridentItem = ben.copy();
        this.entityData.<Byte>set(ThrownTrident.ID_LOYALTY, (byte)EnchantmentHelper.getLoyalty(ben));
        this.entityData.<Boolean>set(ThrownTrident.ID_FOIL, ben.hasFoil());
    }
    
    public ThrownTrident(final Level bjw, final double double2, final double double3, final double double4) {
        super(EntityType.TRIDENT, double2, double3, double4, bjw);
        this.tridentItem = new ItemStack(Items.TRIDENT);
    }
    
    @Override
    protected void defineSynchedData() {
        super.defineSynchedData();
        this.entityData.<Byte>define(ThrownTrident.ID_LOYALTY, (Byte)0);
        this.entityData.<Boolean>define(ThrownTrident.ID_FOIL, false);
    }
    
    @Override
    public void tick() {
        if (this.inGroundTime > 4) {
            this.dealtDamage = true;
        }
        final Entity akq2 = this.getOwner();
        if ((this.dealtDamage || this.isNoPhysics()) && akq2 != null) {
            final int integer3 = this.entityData.<Byte>get(ThrownTrident.ID_LOYALTY);
            if (integer3 > 0 && !this.isAcceptibleReturnOwner()) {
                if (!this.level.isClientSide && this.pickup == Pickup.ALLOWED) {
                    this.spawnAtLocation(this.getPickupItem(), 0.1f);
                }
                this.remove();
            }
            else if (integer3 > 0) {
                this.setNoPhysics(true);
                final Vec3 cvl4 = new Vec3(akq2.getX() - this.getX(), akq2.getEyeY() - this.getY(), akq2.getZ() - this.getZ());
                this.setPosRaw(this.getX(), this.getY() + cvl4.y * 0.015 * integer3, this.getZ());
                if (this.level.isClientSide) {
                    this.yOld = this.getY();
                }
                final double double5 = 0.05 * integer3;
                this.setDeltaMovement(this.getDeltaMovement().scale(0.95).add(cvl4.normalize().scale(double5)));
                if (this.clientSideReturnTridentTickCount == 0) {
                    this.playSound(SoundEvents.TRIDENT_RETURN, 10.0f, 1.0f);
                }
                ++this.clientSideReturnTridentTickCount;
            }
        }
        super.tick();
    }
    
    private boolean isAcceptibleReturnOwner() {
        final Entity akq2 = this.getOwner();
        return akq2 != null && akq2.isAlive() && (!(akq2 instanceof ServerPlayer) || !akq2.isSpectator());
    }
    
    @Override
    protected ItemStack getPickupItem() {
        return this.tridentItem.copy();
    }
    
    public boolean isFoil() {
        return this.entityData.<Boolean>get(ThrownTrident.ID_FOIL);
    }
    
    @Nullable
    @Override
    protected EntityHitResult findHitEntity(final Vec3 cvl1, final Vec3 cvl2) {
        if (this.dealtDamage) {
            return null;
        }
        return super.findHitEntity(cvl1, cvl2);
    }
    
    @Override
    protected void onHitEntity(final EntityHitResult cvh) {
        final Entity akq3 = cvh.getEntity();
        float float4 = 8.0f;
        if (akq3 instanceof LivingEntity) {
            final LivingEntity akz5 = (LivingEntity)akq3;
            float4 += EnchantmentHelper.getDamageBonus(this.tridentItem, akz5.getMobType());
        }
        final Entity akq4 = this.getOwner();
        final DamageSource ajz6 = DamageSource.trident(this, (akq4 == null) ? this : akq4);
        this.dealtDamage = true;
        SoundEvent aah7 = SoundEvents.TRIDENT_HIT;
        if (akq3.hurt(ajz6, float4)) {
            if (akq3.getType() == EntityType.ENDERMAN) {
                return;
            }
            if (akq3 instanceof LivingEntity) {
                final LivingEntity akz6 = (LivingEntity)akq3;
                if (akq4 instanceof LivingEntity) {
                    EnchantmentHelper.doPostHurtEffects(akz6, akq4);
                    EnchantmentHelper.doPostDamageEffects((LivingEntity)akq4, akz6);
                }
                this.doPostHurtEffects(akz6);
            }
        }
        this.setDeltaMovement(this.getDeltaMovement().multiply(-0.01, -0.1, -0.01));
        float float5 = 1.0f;
        if (this.level instanceof ServerLevel && this.level.isThundering() && EnchantmentHelper.hasChanneling(this.tridentItem)) {
            final BlockPos fk9 = akq3.getCommandSenderBlockPosition();
            if (this.level.canSeeSky(fk9)) {
                final LightningBolt avy10 = new LightningBolt(this.level, fk9.getX() + 0.5, fk9.getY(), fk9.getZ() + 0.5, false);
                avy10.setCause((akq4 instanceof ServerPlayer) ? ((ServerPlayer)akq4) : null);
                ((ServerLevel)this.level).addGlobalEntity(avy10);
                aah7 = SoundEvents.TRIDENT_THUNDER;
                float5 = 5.0f;
            }
        }
        this.playSound(aah7, float5, 1.0f);
    }
    
    @Override
    protected SoundEvent getDefaultHitGroundSoundEvent() {
        return SoundEvents.TRIDENT_HIT_GROUND;
    }
    
    @Override
    public void playerTouch(final Player ayj) {
        final Entity akq3 = this.getOwner();
        if (akq3 != null && akq3.getUUID() != ayj.getUUID()) {
            return;
        }
        super.playerTouch(ayj);
    }
    
    @Override
    public void readAdditionalSaveData(final CompoundTag jt) {
        super.readAdditionalSaveData(jt);
        if (jt.contains("Trident", 10)) {
            this.tridentItem = ItemStack.of(jt.getCompound("Trident"));
        }
        this.dealtDamage = jt.getBoolean("DealtDamage");
        this.entityData.<Byte>set(ThrownTrident.ID_LOYALTY, (byte)EnchantmentHelper.getLoyalty(this.tridentItem));
    }
    
    @Override
    public void addAdditionalSaveData(final CompoundTag jt) {
        super.addAdditionalSaveData(jt);
        jt.put("Trident", this.tridentItem.save(new CompoundTag()));
        jt.putBoolean("DealtDamage", this.dealtDamage);
    }
    
    public void tickDespawn() {
        final int integer2 = this.entityData.<Byte>get(ThrownTrident.ID_LOYALTY);
        if (this.pickup != Pickup.ALLOWED || integer2 <= 0) {
            super.tickDespawn();
        }
    }
    
    @Override
    protected float getWaterInertia() {
        return 0.99f;
    }
    
    @Override
    public boolean shouldRender(final double double1, final double double2, final double double3) {
        return true;
    }
    
    static {
        ID_LOYALTY = SynchedEntityData.<Byte>defineId(ThrownTrident.class, EntityDataSerializers.BYTE);
        ID_FOIL = SynchedEntityData.<Boolean>defineId(ThrownTrident.class, EntityDataSerializers.BOOLEAN);
    }
}
