package common.entity.item;

import common.block.artificial.BlockFence;
import common.entity.DamageSource;
import common.entity.Entity;
import common.entity.EntityType;
import common.entity.npc.EntityNPC;
import common.entity.types.EntityLiving;
import common.init.Items;
import common.item.Item;
import common.item.ItemStack;
import common.tags.TagObject;
import common.util.BlockPos;
import common.util.BoundingBox;
import common.util.ExtMath;
import common.world.World;

public class EntityLeashKnot extends Entity
{
    private int checkTimer;
    private BlockPos fencePos;

//    /** The direction the entity is facing */
//    public Facing facingDirection;
    
    public EntityLeashKnot(World worldIn)
    {
        super(worldIn);
        this.setSize(0.5F, 0.5F);
    }

    public EntityLeashKnot(World worldIn, BlockPos fence)
    {
        super(worldIn);
        this.fencePos = fence;
        this.setPosition((double)fence.getX() + 0.5D, (double)fence.getY() + 0.5D, (double)fence.getZ() + 0.5D);
        float f = 0.125F;
        float f1 = 0.1875F;
        float f2 = 0.25F;
        this.setEntityBoundingBox(new BoundingBox(this.posX - 0.1875D, this.posY - 0.25D + 0.125D, this.posZ - 0.1875D, this.posX + 0.1875D, this.posY + 0.25D + 0.125D, this.posZ + 0.1875D));
    }

    public EntityLeashKnot(World worldIn, double x, double y, double z)
    {
    	this(worldIn, new BlockPos(ExtMath.floord(x), ExtMath.floord(y), ExtMath.floord(z)));
    }

    protected void entityInit()
    {
    }

//    /**
//     * Updates facing and bounding box based on it
//     */
//    protected void updateFacingWithBoundingBox(Facing facingDirectionIn)
//    {
//        if (facingDirectionIn == null) {
//			throw new NullPointerException("Facing is null");
//		}
//        if (!facingDirectionIn.getAxis().isHorizontal()) {
//			throw new IllegalArgumentException("Invalid facing");
//		}
//        this.facingDirection = facingDirectionIn;
//        this.prevYaw = this.rotYaw = (float)(this.facingDirection.getHorizontalIndex() * 90);
//        this.updateBoundingBox();
//    }

//    /**
//     * Updates the entity bounding box based on current facing
//     */
//    private void updateBoundingBox()
//    {
//        if (this.facingDirection != null)
//        {
//            double d0 = (double)this.hangingPosition.getX() + 0.5D;
//            double d1 = (double)this.hangingPosition.getY() + 0.5D;
//            double d2 = (double)this.hangingPosition.getZ() + 0.5D;
//            double d3 = 0.46875D;
//            double d4 = 0.0; // this.func_174858_a(this.getWidthPixels());
//            double d5 = 0.0; // this.func_174858_a(this.getHeightPixels());
//            d0 = d0 - (double)this.facingDirection.getFrontOffsetX() * 0.46875D;
//            d2 = d2 - (double)this.facingDirection.getFrontOffsetZ() * 0.46875D;
//            d1 = d1 + d5;
//            Facing enumfacing = this.facingDirection.rotateYCCW();
//            d0 = d0 + d4 * (double)enumfacing.getFrontOffsetX();
//            d2 = d2 + d4 * (double)enumfacing.getFrontOffsetZ();
//            this.posX = d0;
//            this.posY = d1;
//            this.posZ = d2;
//            double d6 = 9.0; // (double)this.getWidthPixels();
//            double d7 = 9.0; // (double)this.getHeightPixels();
//            double d8 = 9.0; // (double)this.getWidthPixels();
//
//            if (this.facingDirection.getAxis() == Facing.Axis.Z)
//            {
//                d8 = 1.0D;
//            }
//            else
//            {
//                d6 = 1.0D;
//            }
//
//            d6 = d6 / 32.0D;
//            d7 = d7 / 32.0D;
//            d8 = d8 / 32.0D;
//            this.setEntityBoundingBox(new BoundingBox(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8));
//        }
//    }

//    private double func_174858_a(int s)
//    {
//        return s % 32 == 0 ? 0.5D : 0.0D;
//    }

    /**
     * Called to update the entity's position/logic.
     */
    public void onUpdate()
    {
        this.prevX = this.posX;
        this.prevY = this.posY;
        this.prevZ = this.posZ;

        if (this.checkTimer++ == 100 && !this.worldObj.client)
        {
            this.checkTimer = 0;

            if (!this.dead && !(this.worldObj.getState(this.fencePos).getBlock() instanceof BlockFence))
            {
                this.setDead();
//                this.onBroken((Entity)null);
            }
        }
    }

//    /**
//     * checks to make sure painting can be placed there
//     */
//    public boolean onValidSurface()
//    {
//        if (!this.worldObj.getCollidingBoundingBoxes(this, this.getEntityBoundingBox()).isEmpty())
//        {
//            return false;
//        }
//        else
//        {
//            int i = Math.max(1, this.getWidthPixels() / 16);
//            int j = Math.max(1, this.getHeightPixels() / 16);
//            BlockPos blockpos = this.hangingPosition.offset(this.facingDirection.getOpposite());
//            Facing enumfacing = this.facingDirection.rotateYCCW();
//
//            for (int k = 0; k < i; ++k)
//            {
//                for (int l = 0; l < j; ++l)
//                {
//                    BlockPos blockpos1 = blockpos.offset(enumfacing, k).up(l);
//                    Block block = this.worldObj.getState(blockpos1).getBlock();
//
//                    if (!block.getMaterial().isSolid() && !BlockRedstoneDiode.isRedstoneRepeaterBlockID(block))
//                    {
//                        return false;
//                    }
//                }
//            }
//
//            for (Entity entity : this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox()))
//            {
//                if (entity instanceof EntityLeashKnot)
//                {
//                    return false;
//                }
//            }
//
//            return true;
//        }
//    }

    /**
     * Returns true if other Entities should be prevented from moving through this Entity.
     */
    public boolean canBeCollidedWith()
    {
        return true;
    }

    /**
     * Called when a player attacks an entity. If this returns true the attack will not happen.
     */
    public boolean hitByEntity(Entity entityIn)
    {
        return entityIn instanceof EntityNPC ? this.attackEntityFrom(DamageSource.causeMobDamage((EntityNPC)entityIn), 0) : false;
    }

//    public Facing getHorizontalFacing()
//    {
//        return this.facingDirection;
//    }

    /**
     * Called when the entity is attacked.
     */
    public boolean attackEntityFrom(DamageSource source, int amount)
    {
//        if (this.isEntityInvulnerable(source))
//        {
//            return false;
//        }
//        else
//        {
        if (!this.dead && !this.worldObj.client)
        {
            this.setDead();
            this.setBeenAttacked();
//                this.onBroken(source.getEntity());
        }

        return true;
//        }
    }

    /**
     * Tries to moves the entity by the passed in displacement. Args: x, y, z
     */
    public void moveEntity(double x, double y, double z)
    {
        if (!this.worldObj.client && !this.dead && x * x + y * y + z * z > 0.0D)
        {
            this.setDead();
//            this.onBroken((Entity)null);
        }
    }

    /**
     * Adds to the current velocity of the entity. Args: x, y, z
     */
    public void addVelocity(double x, double y, double z)
    {
        if (!this.worldObj.client && !this.dead && x * x + y * y + z * z > 0.0D)
        {
            this.setDead();
//            this.onBroken((Entity)null);
        }
    }

//    /**
//     * (abstract) Protected helper method to write subclass entity data to NBT.
//     */
//    public void writeEntityToNBT(NBTTagCompound tagCompound)
//    {
//        tagCompound.setByte("Facing", (byte)this.facingDirection.getHorizontalIndex());
//        tagCompound.setInteger("TileX", this.getHangingPosition().getX());
//        tagCompound.setInteger("TileY", this.getHangingPosition().getY());
//        tagCompound.setInteger("TileZ", this.getHangingPosition().getZ());
//    }
//
//    /**
//     * (abstract) Protected helper method to read subclass entity data from NBT.
//     */
//    public void readEntityFromNBT(NBTTagCompound tagCompund)
//    {
//        this.hangingPosition = new BlockPos(tagCompund.getInteger("TileX"), tagCompund.getInteger("TileY"), tagCompund.getInteger("TileZ"));
//        Facing enumfacing;
//
//        if (tagCompund.hasKey("Direction", 99))
//        {
//            enumfacing = Facing.getHorizontal(tagCompund.getByte("Direction"));
//            this.hangingPosition = this.hangingPosition.offset(enumfacing);
//        }
//        else if (tagCompund.hasKey("Facing", 99))
//        {
//            enumfacing = Facing.getHorizontal(tagCompund.getByte("Facing"));
//        }
//        else
//        {
//            enumfacing = Facing.getHorizontal(tagCompund.getByte("Dir"));
//        }
//
//        this.updateFacingWithBoundingBox(enumfacing);
//    }

//    public abstract int getWidthPixels();
//
//    public abstract int getHeightPixels();

//    /**
//     * Called when this entity is broken. Entity parameter may be null.
//     */
//    public abstract void onBroken(Entity brokenEntity);

    protected boolean shouldSetPosAfterLoading()
    {
        return false;
    }

    /**
     * Sets the x,y,z of the entity from the given parameters. Also seems to set up a bounding box.
     */
    public void setPosition(double x, double y, double z)
    {
        this.posX = x;
        this.posY = y;
        this.posZ = z;
        BlockPos blockpos = this.fencePos;
        this.fencePos = new BlockPos(x, y, z);

        if (!this.fencePos.equals(blockpos))
        {
//            this.updateBoundingBox();
            this.isAirBorne = true;
        }
    }

    public BlockPos getHangingPosition()
    {
        return this.fencePos;
    }
    
    public int getTrackingRange() {
    	return 160;
    }
    
    public int getUpdateFrequency() {
    	return Integer.MAX_VALUE;
    }
    
    public boolean isSendingVeloUpdates() {
    	return false;
    }

//    protected void entityInit()
//    {
//        super.entityInit();
//    }

//    /**
//     * Updates facing and bounding box based on it
//     */
//    public void updateFacingWithBoundingBox(Facing facingDirectionIn)
//    {
//    }

//    public int getWidthPixels()
//    {
//        return 9;
//    }
//
//    public int getHeightPixels()
//    {
//        return 9;
//    }

    public float getEyeHeight()
    {
        return -0.0625F;
    }

    /**
     * Checks if the entity is in range to render by using the past in distance and comparing it to its average edge
     * length * 64 * renderDistanceWeight Args: distance
     */
    public boolean isInRangeToRenderDist(double distance)
    {
        return distance < 1024.0D;
    }

//    /**
//     * Called when this entity is broken. Entity parameter may be null.
//     */
//    public void onBroken(Entity brokenEntity)
//    {
//    }

    /**
     * Either write this entity to the NBT tag given and return true, or return false without doing anything. If this
     * returns false the entity is not saved on disk. Ridden entities return false here as they are saved with their
     * rider.
     */
    public boolean writeOptional(TagObject tagCompund)
    {
        return false;
    }

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

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

    /**
     * First layer of player interaction
     */
    public boolean interactFirst(EntityNPC playerIn)
    {
        ItemStack itemstack = playerIn.getHeldItem();
        boolean flag = false;

        if (itemstack != null && itemstack.getItem() == Items.lead && !this.worldObj.client)
        {
            double d0 = 7.0D;

            for (EntityLiving entityliving : this.worldObj.getEntitiesWithinAABB(EntityLiving.class, new BoundingBox(this.posX - d0, this.posY - d0, this.posZ - d0, this.posX + d0, this.posY + d0, this.posZ + d0)))
            {
                if (entityliving.getLeashed() && entityliving.getLeashedTo() == playerIn)
                {
                    entityliving.setLeashedTo(this, true);
                    flag = true;
                }
            }
        }

        if (!this.worldObj.client && !flag)
        {
            this.setDead();

//            if (playerIn.creative)
//            {
//                double d1 = 7.0D;
//
//                for (EntityLiving entityliving1 : this.worldObj.getEntitiesWithinAABB(EntityLiving.class, new BoundingBox(this.posX - d1, this.posY - d1, this.posZ - d1, this.posX + d1, this.posY + d1, this.posZ + d1)))
//                {
//                    if (entityliving1.getLeashed() && entityliving1.getLeashedTo() == this)
//                    {
//                        entityliving1.clearLeashed(true, false);
//                    }
//                }
//            }
        }

        return true;
    }

    public Item getItem() {
        return Items.lead;
    }
    
    public EntityType getType() {
    	return EntityType.OBJECT;
    }

    public static EntityLeashKnot createKnot(World worldIn, BlockPos fence)
    {
        EntityLeashKnot entityleashknot = new EntityLeashKnot(worldIn, fence);
        entityleashknot.forceSpawn = true;
        worldIn.spawnEntityInWorld(entityleashknot);
        return entityleashknot;
    }

    public static EntityLeashKnot getKnotForPosition(World worldIn, BlockPos pos)
    {
        int i = pos.getX();
        int j = pos.getY();
        int k = pos.getZ();

        for (EntityLeashKnot entityleashknot : worldIn.getEntitiesWithinAABB(EntityLeashKnot.class, new BoundingBox((double)i - 1.0D, (double)j - 1.0D, (double)k - 1.0D, (double)i + 1.0D, (double)j + 1.0D, (double)k + 1.0D)))
        {
            if (entityleashknot.getHangingPosition().equals(pos))
            {
                return entityleashknot;
            }
        }

        return null;
    }
}
