package common.packet;

import java.io.IOException;

import common.entity.Entity;
import common.entity.item.EntityLeashKnot;
import common.entity.projectile.EntityProjectile;
import common.entity.types.IObjectData;
import common.init.EntityRegistry;
import common.network.IClientPlayer;
import common.network.Packet;
import common.network.PacketBuffer;
import common.util.BlockPos;
import common.util.ExtMath;
import common.util.Vec3;

public class SPacketSpawnObject implements Packet<IClientPlayer>
{
    private int entityId;
    private int x;
    private int y;
    private int z;
    private boolean hasSpeed;
    private int speedX;
    private int speedY;
    private int speedZ;
    private int pitch;
    private int yaw;
    private int type;
    private int data;

    public SPacketSpawnObject()
    {
    }

    public SPacketSpawnObject(Entity entityIn)
    {
        this.entityId = entityIn.getId();
        int data = 0;
		if(entityIn instanceof IObjectData)
			data = ((IObjectData)entityIn).getPacketData();
		if(entityIn instanceof EntityLeashKnot) {
			BlockPos pos = ((EntityLeashKnot)entityIn).getHangingPosition();
			this.x = ExtMath.floorf((float)(pos.getX() * 32));
			this.y = ExtMath.floorf((float)(pos.getY() * 32));
			this.z = ExtMath.floorf((float)(pos.getZ() * 32));
		}
		else {
	        this.x = ExtMath.floord(entityIn.posX * 32.0D);
	        this.y = ExtMath.floord(entityIn.posY * 32.0D);
	        this.z = ExtMath.floord(entityIn.posZ * 32.0D);
		}
        this.pitch = ExtMath.floorf(entityIn.rotPitch * 256.0F / 360.0F);
        this.yaw = ExtMath.floorf(entityIn.rotYaw * 256.0F / 360.0F);
        this.type = EntityRegistry.getEntityID(entityIn);
        this.data = data;
		if(entityIn instanceof EntityProjectile) {
			Vec3 accel = ((EntityProjectile)entityIn).getAcceleration();
			this.speedX = (int)(accel.xCoord * 8000.0D);
            this.speedY = (int)(accel.yCoord * 8000.0D);
            this.speedZ = (int)(accel.zCoord * 8000.0D);
            this.hasSpeed = true;
		}
		else if(entityIn.hasSpawnVelocity()) {
            double d0 = entityIn.motionX;
            double d1 = entityIn.motionY;
            double d2 = entityIn.motionZ;
            double d3 = 3.9D;

            if (d0 < -d3)
            {
                d0 = -d3;
            }

            if (d1 < -d3)
            {
                d1 = -d3;
            }

            if (d2 < -d3)
            {
                d2 = -d3;
            }

            if (d0 > d3)
            {
                d0 = d3;
            }

            if (d1 > d3)
            {
                d1 = d3;
            }

            if (d2 > d3)
            {
                d2 = d3;
            }

            this.speedX = (int)(d0 * 8000.0D);
            this.speedY = (int)(d1 * 8000.0D);
            this.speedZ = (int)(d2 * 8000.0D);
            this.hasSpeed = true;
        }
    }
    
    public void readPacketData(PacketBuffer buf) throws IOException
    {
        this.entityId = buf.readVarInt();
        this.type = buf.readUnsignedShort();
        this.x = buf.readInt();
        this.y = buf.readInt();
        this.z = buf.readInt();
        this.pitch = buf.readByte();
        this.yaw = buf.readByte();
        this.data = buf.readInt();
        if(this.hasSpeed = buf.readBoolean()) {
            this.speedX = buf.readShort();
            this.speedY = buf.readShort();
            this.speedZ = buf.readShort();
        }
    }
    
    public void writePacketData(PacketBuffer buf) throws IOException
    {
        buf.writeVarInt(this.entityId);
        buf.writeShort(this.type & 65535);
        buf.writeInt(this.x);
        buf.writeInt(this.y);
        buf.writeInt(this.z);
        buf.writeByte(this.pitch);
        buf.writeByte(this.yaw);
        buf.writeInt(this.data);
        buf.writeBoolean(this.hasSpeed);
        if(this.hasSpeed) {
            buf.writeShort(this.speedX);
            buf.writeShort(this.speedY);
            buf.writeShort(this.speedZ);
        }
    }
    
    public void processPacket(IClientPlayer handler)
    {
        handler.handleSpawnObject(this);
    }

    public int getEntityID()
    {
        return this.entityId;
    }

    public int getX()
    {
        return this.x;
    }

    public int getY()
    {
        return this.y;
    }

    public int getZ()
    {
        return this.z;
    }

    public int getSpeedX()
    {
        return this.speedX;
    }

    public int getSpeedY()
    {
        return this.speedY;
    }

    public int getSpeedZ()
    {
        return this.speedZ;
    }

    public int getPitch()
    {
        return this.pitch;
    }

    public int getYaw()
    {
        return this.yaw;
    }

    public int getType()
    {
        return this.type;
    }

    public int getData()
    {
        return this.data;
    }
}
