package common.entity.projectile;

import java.util.List;

import common.entity.types.EntityLiving;
import common.entity.types.EntityThrowable;
import common.entity.types.IObjectData;
import common.init.Items;
import common.item.ItemStack;
import common.item.tool.ItemPotion;
import common.potion.Potion;
import common.potion.PotionEffect;
import common.tags.TagObject;
import common.util.BlockPos;
import common.util.BoundingBox;
import common.util.HitPosition;
import common.world.World;

public class EntityPotion extends EntityThrowable implements IObjectData
{
    private ItemStack potionDamage;

    public EntityPotion(World worldIn)
    {
        super(worldIn);
    }

    public EntityPotion(World worldIn, EntityLiving throwerIn, int meta)
    {
        this(worldIn, throwerIn, new ItemStack(ItemPotion.getPotionItem(meta)));
    }

    public EntityPotion(World worldIn, EntityLiving throwerIn, ItemStack potionDamageIn)
    {
        super(worldIn, throwerIn);
        this.potionDamage = potionDamageIn;
    }

    public EntityPotion(World worldIn, double x, double y, double z, int data)
    {
        this(worldIn, x, y, z, new ItemStack(ItemPotion.getPotionItem(data)));
    }

    public EntityPotion(World worldIn, double x, double y, double z, ItemStack potionDamageIn)
    {
        super(worldIn, x, y, z);
        this.potionDamage = potionDamageIn;
    }

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

    protected float getVelocity()
    {
        return 0.5F;
    }

    protected float getInaccuracy()
    {
        return -20.0F;
    }

    /**
     * Sets the PotionEffect by the given id of the potion effect.
     */
    public void setPotionDamage(int potionId)
    {
        this.potionDamage = new ItemStack(ItemPotion.getPotionItem(potionId));
    }

    /**
     * Returns the damage value of the thrown potion that this EntityPotion represents.
     */
    public int getPotionDamage()
    {
        if (this.potionDamage == null)
        {
            this.potionDamage = new ItemStack(Items.potion);
        }

        return this.potionDamage.getItem() instanceof ItemPotion potion ? potion.getPotionData() : 0;
    }

    /**
     * Called when this EntityThrowable hits a block or entity.
     */
    protected void onImpact(HitPosition p_70184_1_)
    {
        if (!this.worldObj.client)
        {
            List<PotionEffect> list = this.potionDamage != null && this.potionDamage.getItem() instanceof ItemPotion potion ? potion.getEffects() : null;

            BoundingBox axisalignedbb = this.getEntityBoundingBox().expand(4.0D, 2.0D, 4.0D);
            List<EntityLiving> list1 = this.worldObj.<EntityLiving>getEntitiesWithinAABB(EntityLiving.class, axisalignedbb);

            if (!list1.isEmpty())
            {
                for (EntityLiving entitylivingbase : list1)
                {
                    double d0 = this.getDistanceSqToEntity(entitylivingbase);

                    if (d0 < 16.0D)
                    {
                        if (list != null && !list.isEmpty())
                        {
                            double d1 = 1.0D - Math.sqrt(d0) / 4.0D;

                            if (entitylivingbase == p_70184_1_.entity)
                            {
                                d1 = 1.0D;
                            }
                            
                            for (PotionEffect potioneffect : list)
                            {
                                Potion i = potioneffect.getPotion();
                                if(!entitylivingbase.isPotionApplicable(i, potioneffect.getAmplifier()))
                                	continue;

                                if (i.isInstant())
                                {
                                    i.onImpact(this, this.getThrower(), entitylivingbase, potioneffect.getAmplifier(), d1);
                                }
                                else
                                {
                                    int j = (int)(d1 * (double)potioneffect.getDuration() + 0.5D);

                                    if (j > 20)
                                    {
                                        entitylivingbase.addEffect(new PotionEffect(i, j, potioneffect.getAmplifier()));
                                    }
                                }
                            }
                        }
                        else {
                        	entitylivingbase.extinguish();
                        }
                    }
                }
            }

            this.worldObj.playAuxSFX(2002, new BlockPos(this), this.getPotionDamage());
            this.setDead();
        }
    }

    /**
     * (abstract) Protected helper method to read subclass entity data from NBT.
     */
    public void readEntity(TagObject tagCompund)
    {
        super.readEntity(tagCompund);

        if (tagCompund.hasObject("Potion"))
        {
            this.potionDamage = ItemStack.readFromTag(tagCompund.getObject("Potion"));
        }
        else
        {
            this.setPotionDamage(tagCompund.getInt("potionValue"));
        }

        if (this.potionDamage == null || !(this.potionDamage.getItem() instanceof ItemPotion))
        {
            this.setDead();
        }
    }

    /**
     * (abstract) Protected helper method to write subclass entity data to NBT.
     */
    public void writeEntity(TagObject tagCompound)
    {
        super.writeEntity(tagCompound);

        if (this.potionDamage != null)
        {
            tagCompound.setObject("Potion", this.potionDamage.writeTags(new TagObject()));
        }
    }
	
	public int getPacketData() {
		return this.getPotionDamage();
	}
	
//	public boolean hasSpawnVelocity() {
//		return false;
//	}
}
