package electrosphere.net.parser.net.message;

import electrosphere.net.parser.util.ByteStreamUtils;
import java.util.LinkedList;
import java.util.List;

public class EntityMessage extends NetworkMessage {

    public enum EntityMessageType {
        CREATE,
        SETPOSITION,
        SETFACING,
        MOVEUPDATE,
        ATTACKUPDATE,
        MOVE,
        DESTROY,
        SETBEHAVIORTREE,
        SETPROPERTY,
        ATTACHENTITYTOENTITY,
    }

    EntityMessageType messageType;
    int entityCategory;
    String entitySubtype;
    int entityID;
    double positionX;
    double positionY;
    double positionZ;
    float rotationW;
    float rotationX;
    float rotationY;
    float rotationZ;
    float velocity;
    int treeState;
    int propertyType;
    int propertyValue;
    int treeType;
    int treeStatus;
    long time;
    String bone;
    int targetID;

    EntityMessage(EntityMessageType messageType){
        this.type = MessageType.ENTITY_MESSAGE;
        this.messageType = messageType;
    }

    public EntityMessageType getMessageSubtype(){
        return this.messageType;
    }

    public int getentityCategory() {
        return entityCategory;
    }

    public void setentityCategory(int entityCategory) {
        this.entityCategory = entityCategory;
    }

    public String getentitySubtype() {
        return entitySubtype;
    }

    public void setentitySubtype(String entitySubtype) {
        this.entitySubtype = entitySubtype;
    }

    public int getentityID() {
        return entityID;
    }

    public void setentityID(int entityID) {
        this.entityID = entityID;
    }

    public double getpositionX() {
        return positionX;
    }

    public void setpositionX(double positionX) {
        this.positionX = positionX;
    }

    public double getpositionY() {
        return positionY;
    }

    public void setpositionY(double positionY) {
        this.positionY = positionY;
    }

    public double getpositionZ() {
        return positionZ;
    }

    public void setpositionZ(double positionZ) {
        this.positionZ = positionZ;
    }

    public float getrotationW() {
        return rotationW;
    }

    public void setrotationW(float rotationW) {
        this.rotationW = rotationW;
    }

    public float getrotationX() {
        return rotationX;
    }

    public void setrotationX(float rotationX) {
        this.rotationX = rotationX;
    }

    public float getrotationY() {
        return rotationY;
    }

    public void setrotationY(float rotationY) {
        this.rotationY = rotationY;
    }

    public float getrotationZ() {
        return rotationZ;
    }

    public void setrotationZ(float rotationZ) {
        this.rotationZ = rotationZ;
    }

    public float getvelocity() {
        return velocity;
    }

    public void setvelocity(float velocity) {
        this.velocity = velocity;
    }

    public int gettreeState() {
        return treeState;
    }

    public void settreeState(int treeState) {
        this.treeState = treeState;
    }

    public int getpropertyType() {
        return propertyType;
    }

    public void setpropertyType(int propertyType) {
        this.propertyType = propertyType;
    }

    public int getpropertyValue() {
        return propertyValue;
    }

    public void setpropertyValue(int propertyValue) {
        this.propertyValue = propertyValue;
    }

    public int gettreeType() {
        return treeType;
    }

    public void settreeType(int treeType) {
        this.treeType = treeType;
    }

    public int gettreeStatus() {
        return treeStatus;
    }

    public void settreeStatus(int treeStatus) {
        this.treeStatus = treeStatus;
    }

    public long gettime() {
        return time;
    }

    public void settime(long time) {
        this.time = time;
    }

    public String getbone() {
        return bone;
    }

    public void setbone(String bone) {
        this.bone = bone;
    }

    public int gettargetID() {
        return targetID;
    }

    public void settargetID(int targetID) {
        this.targetID = targetID;
    }

    static void stripPacketHeader(List<Byte> byteStream){
        byteStream.remove(0);
        byteStream.remove(0);
    }

    public static boolean canParseMessage(List<Byte> byteStream, byte secondByte){
        switch(secondByte){
            case TypeBytes.ENTITY_MESSAGE_TYPE_CREATE:
                return EntityMessage.canParseCreateMessage(byteStream);
            case TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION:
                if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_SETFACING:
                if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETFACING_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE:
                if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE:
                if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_MOVE:
                if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_MOVE_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY:
                if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE:
                if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY:
                if(byteStream.size() >= TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY:
                return EntityMessage.canParseattachEntityToEntityMessage(byteStream);
        }
        return false;
    }

    public static boolean canParseCreateMessage(List<Byte> byteStream){
        int currentStreamLength = byteStream.size();
        List<Byte> temporaryByteQueue = new LinkedList();
        if(currentStreamLength < 6){
            return false;
        }
        if(currentStreamLength < 10){
            return false;
        }
        int entitySubtypeSize = 0;
        if(currentStreamLength < 14){
            return false;
        } else {
            temporaryByteQueue.add(byteStream.get(10 + 0));
            temporaryByteQueue.add(byteStream.get(10 + 1));
            temporaryByteQueue.add(byteStream.get(10 + 2));
            temporaryByteQueue.add(byteStream.get(10 + 3));
            entitySubtypeSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
        }
        if(currentStreamLength < 14 + entitySubtypeSize){
            return false;
        }
        if(currentStreamLength < 18){
            return false;
        }
        if(currentStreamLength < 26){
            return false;
        }
        if(currentStreamLength < 34){
            return false;
        }
        return true;
    }

    public static EntityMessage parseCreateMessage(List<Byte> byteStream){
        EntityMessage rVal = new EntityMessage(EntityMessageType.CREATE);
        stripPacketHeader(byteStream);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.setentityCategory(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.setentitySubtype(ByteStreamUtils.popStringFromByteQueue(byteStream));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        return rVal;
    }

    public static EntityMessage constructCreateMessage(int entityID,int entityCategory,String entitySubtype,double positionX,double positionY,double positionZ){
        EntityMessage rVal = new EntityMessage(EntityMessageType.CREATE);
        rVal.setentityID(entityID);
        rVal.setentityCategory(entityCategory);
        rVal.setentitySubtype(entitySubtype);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parseSetPositionMessage(List<Byte> byteStream){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SETPOSITION);
        stripPacketHeader(byteStream);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        return rVal;
    }

    public static EntityMessage constructSetPositionMessage(int entityID,long time,double positionX,double positionY,double positionZ){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SETPOSITION);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parsesetFacingMessage(List<Byte> byteStream){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SETFACING);
        stripPacketHeader(byteStream);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream));
        rVal.setrotationX(ByteStreamUtils.popFloatFromByteQueue(byteStream));
        rVal.setrotationY(ByteStreamUtils.popFloatFromByteQueue(byteStream));
        rVal.setrotationZ(ByteStreamUtils.popFloatFromByteQueue(byteStream));
        return rVal;
    }

    public static EntityMessage constructsetFacingMessage(int entityID,long time,float rotationX,float rotationY,float rotationZ){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SETFACING);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.setrotationX(rotationX);
        rVal.setrotationY(rotationY);
        rVal.setrotationZ(rotationZ);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parsemoveUpdateMessage(List<Byte> byteStream){
        EntityMessage rVal = new EntityMessage(EntityMessageType.MOVEUPDATE);
        stripPacketHeader(byteStream);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setrotationX(ByteStreamUtils.popFloatFromByteQueue(byteStream));
        rVal.setrotationY(ByteStreamUtils.popFloatFromByteQueue(byteStream));
        rVal.setrotationZ(ByteStreamUtils.popFloatFromByteQueue(byteStream));
        rVal.setvelocity(ByteStreamUtils.popFloatFromByteQueue(byteStream));
        rVal.settreeState(ByteStreamUtils.popIntFromByteQueue(byteStream));
        return rVal;
    }

    public static EntityMessage constructmoveUpdateMessage(int entityID,long time,double positionX,double positionY,double positionZ,float rotationX,float rotationY,float rotationZ,float velocity,int treeState){
        EntityMessage rVal = new EntityMessage(EntityMessageType.MOVEUPDATE);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.setrotationX(rotationX);
        rVal.setrotationY(rotationY);
        rVal.setrotationZ(rotationZ);
        rVal.setvelocity(velocity);
        rVal.settreeState(treeState);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parseattackUpdateMessage(List<Byte> byteStream){
        EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACKUPDATE);
        stripPacketHeader(byteStream);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setrotationX(ByteStreamUtils.popFloatFromByteQueue(byteStream));
        rVal.setrotationY(ByteStreamUtils.popFloatFromByteQueue(byteStream));
        rVal.setrotationZ(ByteStreamUtils.popFloatFromByteQueue(byteStream));
        rVal.setvelocity(ByteStreamUtils.popFloatFromByteQueue(byteStream));
        rVal.settreeState(ByteStreamUtils.popIntFromByteQueue(byteStream));
        return rVal;
    }

    public static EntityMessage constructattackUpdateMessage(int entityID,long time,double positionX,double positionY,double positionZ,float rotationX,float rotationY,float rotationZ,float velocity,int treeState){
        EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACKUPDATE);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.setrotationX(rotationX);
        rVal.setrotationY(rotationY);
        rVal.setrotationZ(rotationZ);
        rVal.setvelocity(velocity);
        rVal.settreeState(treeState);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parseMoveMessage(List<Byte> byteStream){
        EntityMessage rVal = new EntityMessage(EntityMessageType.MOVE);
        stripPacketHeader(byteStream);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream));
        rVal.setpositionX(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setpositionY(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        rVal.setpositionZ(ByteStreamUtils.popDoubleFromByteQueue(byteStream));
        return rVal;
    }

    public static EntityMessage constructMoveMessage(int entityID,long time,double positionX,double positionY,double positionZ){
        EntityMessage rVal = new EntityMessage(EntityMessageType.MOVE);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.setpositionX(positionX);
        rVal.setpositionY(positionY);
        rVal.setpositionZ(positionZ);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parseDestroyMessage(List<Byte> byteStream){
        EntityMessage rVal = new EntityMessage(EntityMessageType.DESTROY);
        stripPacketHeader(byteStream);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
        return rVal;
    }

    public static EntityMessage constructDestroyMessage(int entityID){
        EntityMessage rVal = new EntityMessage(EntityMessageType.DESTROY);
        rVal.setentityID(entityID);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parseSetBehaviorTreeMessage(List<Byte> byteStream){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SETBEHAVIORTREE);
        stripPacketHeader(byteStream);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream));
        rVal.settreeType(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.settreeStatus(ByteStreamUtils.popIntFromByteQueue(byteStream));
        return rVal;
    }

    public static EntityMessage constructSetBehaviorTreeMessage(int entityID,long time,int treeType,int treeStatus){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SETBEHAVIORTREE);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.settreeType(treeType);
        rVal.settreeStatus(treeStatus);
        rVal.serialize();
        return rVal;
    }

    public static EntityMessage parsesetPropertyMessage(List<Byte> byteStream){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SETPROPERTY);
        stripPacketHeader(byteStream);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteStream));
        rVal.setpropertyType(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.setpropertyValue(ByteStreamUtils.popIntFromByteQueue(byteStream));
        return rVal;
    }

    public static EntityMessage constructsetPropertyMessage(int entityID,long time,int propertyType,int propertyValue){
        EntityMessage rVal = new EntityMessage(EntityMessageType.SETPROPERTY);
        rVal.setentityID(entityID);
        rVal.settime(time);
        rVal.setpropertyType(propertyType);
        rVal.setpropertyValue(propertyValue);
        rVal.serialize();
        return rVal;
    }

    public static boolean canParseattachEntityToEntityMessage(List<Byte> byteStream){
        int currentStreamLength = byteStream.size();
        List<Byte> temporaryByteQueue = new LinkedList();
        if(currentStreamLength < 6){
            return false;
        }
        int boneSize = 0;
        if(currentStreamLength < 10){
            return false;
        } else {
            temporaryByteQueue.add(byteStream.get(6 + 0));
            temporaryByteQueue.add(byteStream.get(6 + 1));
            temporaryByteQueue.add(byteStream.get(6 + 2));
            temporaryByteQueue.add(byteStream.get(6 + 3));
            boneSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
        }
        if(currentStreamLength < 10 + boneSize){
            return false;
        }
        if(currentStreamLength < 10){
            return false;
        }
        return true;
    }

    public static EntityMessage parseattachEntityToEntityMessage(List<Byte> byteStream){
        EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACHENTITYTOENTITY);
        stripPacketHeader(byteStream);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteStream));
        rVal.setbone(ByteStreamUtils.popStringFromByteQueue(byteStream));
        rVal.settargetID(ByteStreamUtils.popIntFromByteQueue(byteStream));
        return rVal;
    }

    public static EntityMessage constructattachEntityToEntityMessage(int entityID,String bone,int targetID){
        EntityMessage rVal = new EntityMessage(EntityMessageType.ATTACHENTITYTOENTITY);
        rVal.setentityID(entityID);
        rVal.setbone(bone);
        rVal.settargetID(targetID);
        rVal.serialize();
        return rVal;
    }

    @Override
    void serialize(){
        byte[] intValues = new byte[8];
        byte[] stringBytes;
        switch(this.messageType){
            case CREATE:
                rawBytes = new byte[2+4+4+4+entitySubtype.length()+8+8+8];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_CREATE;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(entityCategory);
                for(int i = 0; i < 4; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(entitySubtype.length());
                for(int i = 0; i < 4; i++){
                    rawBytes[10+i] = intValues[i];
                }
                stringBytes = entitySubtype.getBytes();
                for(int i = 0; i < entitySubtype.length(); i++){
                    rawBytes[14+i] = stringBytes[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[14+entitySubtype.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[22+entitySubtype.length()+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[30+entitySubtype.length()+i] = intValues[i];
                }
                break;
            case SETPOSITION:
                rawBytes = new byte[2+4+8+8+8+8];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[14+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[22+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[30+i] = intValues[i];
                }
                break;
            case SETFACING:
                rawBytes = new byte[2+4+8+4+4+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SETFACING;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeFloatToBytes(rotationX);
                for(int i = 0; i < 4; i++){
                    rawBytes[14+i] = intValues[i];
                }                intValues = ByteStreamUtils.serializeFloatToBytes(rotationY);
                for(int i = 0; i < 4; i++){
                    rawBytes[18+i] = intValues[i];
                }                intValues = ByteStreamUtils.serializeFloatToBytes(rotationZ);
                for(int i = 0; i < 4; i++){
                    rawBytes[22+i] = intValues[i];
                }                break;
            case MOVEUPDATE:
                rawBytes = new byte[2+4+8+8+8+8+4+4+4+4+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[14+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[22+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[30+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeFloatToBytes(rotationX);
                for(int i = 0; i < 4; i++){
                    rawBytes[38+i] = intValues[i];
                }                intValues = ByteStreamUtils.serializeFloatToBytes(rotationY);
                for(int i = 0; i < 4; i++){
                    rawBytes[42+i] = intValues[i];
                }                intValues = ByteStreamUtils.serializeFloatToBytes(rotationZ);
                for(int i = 0; i < 4; i++){
                    rawBytes[46+i] = intValues[i];
                }                intValues = ByteStreamUtils.serializeFloatToBytes(velocity);
                for(int i = 0; i < 4; i++){
                    rawBytes[50+i] = intValues[i];
                }                intValues = ByteStreamUtils.serializeIntToBytes(treeState);
                for(int i = 0; i < 4; i++){
                    rawBytes[54+i] = intValues[i];
                }
                break;
            case ATTACKUPDATE:
                rawBytes = new byte[2+4+8+8+8+8+4+4+4+4+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[14+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[22+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[30+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeFloatToBytes(rotationX);
                for(int i = 0; i < 4; i++){
                    rawBytes[38+i] = intValues[i];
                }                intValues = ByteStreamUtils.serializeFloatToBytes(rotationY);
                for(int i = 0; i < 4; i++){
                    rawBytes[42+i] = intValues[i];
                }                intValues = ByteStreamUtils.serializeFloatToBytes(rotationZ);
                for(int i = 0; i < 4; i++){
                    rawBytes[46+i] = intValues[i];
                }                intValues = ByteStreamUtils.serializeFloatToBytes(velocity);
                for(int i = 0; i < 4; i++){
                    rawBytes[50+i] = intValues[i];
                }                intValues = ByteStreamUtils.serializeIntToBytes(treeState);
                for(int i = 0; i < 4; i++){
                    rawBytes[54+i] = intValues[i];
                }
                break;
            case MOVE:
                rawBytes = new byte[2+4+8+8+8+8];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_MOVE;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionX);
                for(int i = 0; i < 8; i++){
                    rawBytes[14+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionY);
                for(int i = 0; i < 8; i++){
                    rawBytes[22+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeDoubleToBytes(positionZ);
                for(int i = 0; i < 8; i++){
                    rawBytes[30+i] = intValues[i];
                }
                break;
            case DESTROY:
                rawBytes = new byte[2+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                break;
            case SETBEHAVIORTREE:
                rawBytes = new byte[2+4+8+4+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(treeType);
                for(int i = 0; i < 4; i++){
                    rawBytes[14+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(treeStatus);
                for(int i = 0; i < 4; i++){
                    rawBytes[18+i] = intValues[i];
                }
                break;
            case SETPROPERTY:
                rawBytes = new byte[2+4+8+4+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(propertyType);
                for(int i = 0; i < 4; i++){
                    rawBytes[14+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(propertyValue);
                for(int i = 0; i < 4; i++){
                    rawBytes[18+i] = intValues[i];
                }
                break;
            case ATTACHENTITYTOENTITY:
                rawBytes = new byte[2+4+4+bone.length()+4];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_ENTITY;
                //entity messaage header
                rawBytes[1] = TypeBytes.ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(bone.length());
                for(int i = 0; i < 4; i++){
                    rawBytes[6+i] = intValues[i];
                }
                stringBytes = bone.getBytes();
                for(int i = 0; i < bone.length(); i++){
                    rawBytes[10+i] = stringBytes[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(targetID);
                for(int i = 0; i < 4; i++){
                    rawBytes[10+bone.length()+i] = intValues[i];
                }
                break;
        }
        serialized = true;
    }

}
