package gvclib.entity.bullet;


import com.google.common.collect.Sets;
import gvclib.mod_GVCLib;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.entity.projectile.ThrowableProjectile;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkHooks;
import net.minecraftforge.network.PlayMessages;

import java.util.Set;

public class EntityB_Bullet extends ThrowableProjectile {

    private static final EntityDataAccessor<Float> Gravity = SynchedEntityData.defineId(gvclib.entity.bullet.EntityB_Bullet.class, EntityDataSerializers.FLOAT);

    public int powor = 0;
    public float gra = 0.0299F;//0.0299F
    public float exlevel = 0;
    public boolean flame = false;
    public boolean flare = false;

    private final Set<MobEffectInstance> effects = Sets.newHashSet();


    public EntityB_Bullet(PlayMessages.SpawnEntity packet, Level worldIn) {
        super(mod_GVCLib.ENTITYB_BULLET.get(), worldIn);
    }

    public EntityB_Bullet(EntityType<? extends gvclib.entity.bullet.EntityB_Bullet> p_i50159_1_, Level p_i50159_2_) {
        super(p_i50159_1_, p_i50159_2_);
    }

   /*public EntityBullet(EntityType<EntityBullet> p_i50159_1_, World p_i50159_2_) {
	      super(p_i50159_1_, p_i50159_2_);
	   }*/

    public EntityB_Bullet(Level worldIn, LivingEntity throwerIn) {
        super(mod_GVCLib.ENTITYB_BULLET.get(), throwerIn, worldIn);
    }

    public EntityB_Bullet(Level worldIn, double x, double y, double z) {
        super(mod_GVCLib.ENTITYB_BULLET.get(), x, y, z, worldIn);
    }

    protected Item getDefaultItem() {
        return Items.SNOWBALL;
    }


    protected void defineSynchedData() {
        //  super.defineSynchedData();
        this.getEntityData().define(Gravity, 0.0299F);
    }

    /**
     * (abstract) Protected helper method to read subclass entity data from NBT.
     */
   /*public void readAdditional(CompoundNBT compound) {
      super.readAdditional(compound);
      this.dataManager.set(Gravity, compound.getFloat("Gravity"));
   }

   public void writeAdditional(CompoundNBT compound) {
	      super.writeAdditional(compound);
	      compound.putFloat("Gravity", this.dataManager.get(Gravity));
   }*/
    public void addAdditionalSaveData(CompoundTag compound) {
	      /*if (this.ownerUUID != null) {
	         p_213281_1_.putUUID("Owner", this.ownerUUID);
	      }

	      if (this.leftOwner) {
	         p_213281_1_.putBoolean("LeftOwner", true);
	      }*/
        super.addAdditionalSaveData(compound);
        compound.putFloat("Gravity", this.getEntityData().get(Gravity));
    }

    public void readAdditionalSaveData(CompoundTag compound) {
	     /* if (p_70037_1_.hasUUID("Owner")) {
	         this.ownerUUID = p_70037_1_.getUUID("Owner");
	      }

	      this.leftOwner = p_70037_1_.getBoolean("LeftOwner");*/
        super.readAdditionalSaveData(compound);
        this.getEntityData().set(Gravity, compound.getFloat("Gravity"));
    }


    public float getGravityBullet() {
        return ((this.getEntityData().get(Gravity)).floatValue());
    }
    public void setGravity(float s) {
        this.getEntityData().set(Gravity, Float.valueOf(s));
    }

    /*
    @OnlyIn(Dist.CLIENT)
    private IParticleData getParticle() {
        ItemStack itemstack = this.getItemRaw();
        return (IParticleData)(itemstack.isEmpty() ? ParticleTypes.ITEM_SNOWBALL : new ItemParticleData(ParticleTypes.ITEM, itemstack));
    }
    */


    /**
     * Gets the amount of gravity to apply to the thrown entity with each tick.
     */
    protected float getGravity() {
        return 0.03F - getGravityBullet();
    }

    /**
     * Called to update the entity's position/logic.
     */
    public void tick() {
        super.tick();
        // Vector3d vector3d = this.getDeltaMovement();
        Vec3 vec3 = this.getDeltaMovement();
        double d3 = vec3.x;
        double d4 = vec3.y;
        double d0 = vec3.z;
        // if (this.getIsCritical())
        {
            for(int i = 0; i < 4; ++i) {
                // this.world.addParticle(ParticleTypes.CRIT, this.getPosX() + d3 * (double)i / 4.0D, this.getPosY() + d4 * (double)i / 4.0D, this.getPosZ() + d0 * (double)i / 4.0D, -d3, -d4 + 0.2D, -d0);
                // this.world.addParticle(ParticleTypes.SMOKE, this.getPosX(), this.getPosY(), this.getPosZ(), 0, 0, 0);
            }
        }
        this.level.addParticle(ParticleTypes.SMOKE, this.getX(), this.getY(), this.getZ(), 0, 0, 0);
        //System.out.println(String.format("fry_entity"));
    }


    @OnlyIn(Dist.CLIENT)
    public void handleEntityEvent(byte p_70103_1_) {
        /*if (p_70103_1_ == 3) {
            IParticleData iparticledata = this.getParticle();

            for(int i = 0; i < 8; ++i) {
                this.level.addParticle(iparticledata, this.getX(), this.getY(), this.getZ(), 0.0D, 0.0D, 0.0D);
            }
        }*/

    }

    /**
     * Called when the arrow hits an entity
     */
    protected void onHitEntity(EntityHitResult p_213868_1_) {
        super.onHitEntity(p_213868_1_);
        Entity entity = p_213868_1_.getEntity();
        entity.invulnerableTime = 0;
        int i = powor;
        //entity.attackEntityFrom(DamageSource.causeThrownDamage(this, this.func_234616_v_()), (float)i);
        entity.hurt(DamageSource.thrown(this, this.getOwner()), (float)i);
    }

    /**
     * Called when this EntityFireball hits a block or entity.
     */
    protected void onHit(HitResult result) {
        super.onHit(result);
        if (!this.level.isClientSide) {
            this.level.broadcastEntityEvent(this, (byte)3);
            if(exlevel > 0) {
                this.level.explode(this, this.getX(), this.getY(), this.getZ(), exlevel, false, Explosion.BlockInteraction.NONE);
            }
            //this.world.createExplosion((Entity)null, this.getPosX(), this.getPosY(), this.getPosZ(), 0.0F, false, Explosion.Mode.NONE);
            EntityHitResult.Type raytraceresult$type = result.getType();
            if (raytraceresult$type == EntityHitResult.Type.ENTITY) {
                if(!flame)this.discard();// this.remove();
            }else {
                if(flare)this.level.setBlock(new BlockPos(this.getX(), this.getY(), this.getZ()),
                        Blocks.TORCH.defaultBlockState(), 2);
                this.discard();// this.remove();
            }
        }

    }

    public Packet<?> getAddEntityPacket() {
        //return new ClientboundAddExperienceOrbPacket(this);
        return NetworkHooks.getEntitySpawningPacket(this);
    }

    /*
    @Override
    public IPacket<?> getAddEntityPacket() {
        //return new SSpawnObjectPacket(this);
        return NetworkHooks.getEntitySpawningPacket(this);
    }
    */

   /*@Override
   public IPacket<?> createSpawnPacket() {
	   return NetworkHooks.getEntitySpawningPacket(this);
	   }
	   */

   /*@Override
   public IPacket<?> createSpawnPacket() {
	      Entity entity = this.func_234616_v_();
	      return new SSpawnObjectPacket(this, entity == null ? 0 : entity.getEntityId());
	   }*/
}