package electrosphere.net.parser.net.message;

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

public abstract class NetworkMessage {
    
    public enum MessageType {
STATUS_MESSAGE,
WORLD_MESSAGE,
PLAYER_MESSAGE,
ENTITY_MESSAGE,
    }
    
    MessageType type;
    boolean serialized; // has this message been converted to bytes?
    byte[] rawBytes;

    public MessageType getType() {
        return type;
    }

    public byte[] getRawBytes() {
        return rawBytes;
    }
    
    public static NetworkMessage parseBytestreamForMessage(List<Byte> byteStream){
        NetworkMessage rVal = null;
        byte firstByte;
        byte secondByte;
        if(byteStream.size() > 1){
            firstByte = byteStream.get(0);
            switch(firstByte){
                case TypeBytes.MESSAGE_TYPE_STATUS:
                    secondByte = byteStream.get(1);
                    switch(secondByte){
                    case TypeBytes.STATUS_MESSAGE_TYPE_READY:
                        if(StatusMessage.canParseMessage(byteStream,secondByte)){
                            rVal = StatusMessage.parseReadyMessage(byteStream);
                        }
                        break;
                }
                break;
                case TypeBytes.MESSAGE_TYPE_WORLD:
                    secondByte = byteStream.get(1);
                    switch(secondByte){
                    case TypeBytes.WORLD_MESSAGE_TYPE_METADATA:
                        if(WorldMessage.canParseMessage(byteStream,secondByte)){
                            rVal = WorldMessage.parseMetadataMessage(byteStream);
                        }
                        break;
                    case TypeBytes.WORLD_MESSAGE_TYPE_REQUESTCHUNK:
                        if(WorldMessage.canParseMessage(byteStream,secondByte)){
                            rVal = WorldMessage.parseRequestChunkMessage(byteStream);
                        }
                        break;
                    case TypeBytes.WORLD_MESSAGE_TYPE_UPDATE:
                        if(WorldMessage.canParseMessage(byteStream,secondByte)){
                            rVal = WorldMessage.parseUpdateMessage(byteStream);
                        }
                        break;
                    case TypeBytes.WORLD_MESSAGE_TYPE_CHUNKLOADSTART:
                        if(WorldMessage.canParseMessage(byteStream,secondByte)){
                            rVal = WorldMessage.parsechunkLoadStartMessage(byteStream);
                        }
                        break;
                    case TypeBytes.WORLD_MESSAGE_TYPE_MACROVALUE:
                        if(WorldMessage.canParseMessage(byteStream,secondByte)){
                            rVal = WorldMessage.parseMacroValueMessage(byteStream);
                        }
                        break;
                    case TypeBytes.WORLD_MESSAGE_TYPE_HEIGHTMAPMODIFICATION:
                        if(WorldMessage.canParseMessage(byteStream,secondByte)){
                            rVal = WorldMessage.parseheightMapModificationMessage(byteStream);
                        }
                        break;
                    case TypeBytes.WORLD_MESSAGE_TYPE_SPAWNPOSITION:
                        if(WorldMessage.canParseMessage(byteStream,secondByte)){
                            rVal = WorldMessage.parseSpawnPositionMessage(byteStream);
                        }
                        break;
                }
                break;
                case TypeBytes.MESSAGE_TYPE_PLAYER:
                    secondByte = byteStream.get(1);
                    switch(secondByte){
                    case TypeBytes.PLAYER_MESSAGE_TYPE_SET_ID:
                        if(PlayerMessage.canParseMessage(byteStream,secondByte)){
                            rVal = PlayerMessage.parseSet_IDMessage(byteStream);
                        }
                        break;
                    case TypeBytes.PLAYER_MESSAGE_TYPE_SETINITIALDISCRETEPOSITION:
                        if(PlayerMessage.canParseMessage(byteStream,secondByte)){
                            rVal = PlayerMessage.parseSetInitialDiscretePositionMessage(byteStream);
                        }
                        break;
                }
                break;
                case TypeBytes.MESSAGE_TYPE_ENTITY:
                    secondByte = byteStream.get(1);
                    switch(secondByte){
                    case TypeBytes.ENTITY_MESSAGE_TYPE_CREATE:
                        if(EntityMessage.canParseMessage(byteStream,secondByte)){
                            rVal = EntityMessage.parseCreateMessage(byteStream);
                        }
                        break;
                    case TypeBytes.ENTITY_MESSAGE_TYPE_SETPOSITION:
                        if(EntityMessage.canParseMessage(byteStream,secondByte)){
                            rVal = EntityMessage.parseSetPositionMessage(byteStream);
                        }
                        break;
                    case TypeBytes.ENTITY_MESSAGE_TYPE_SETFACING:
                        if(EntityMessage.canParseMessage(byteStream,secondByte)){
                            rVal = EntityMessage.parsesetFacingMessage(byteStream);
                        }
                        break;
                    case TypeBytes.ENTITY_MESSAGE_TYPE_MOVEUPDATE:
                        if(EntityMessage.canParseMessage(byteStream,secondByte)){
                            rVal = EntityMessage.parsemoveUpdateMessage(byteStream);
                        }
                        break;
                    case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACKUPDATE:
                        if(EntityMessage.canParseMessage(byteStream,secondByte)){
                            rVal = EntityMessage.parseattackUpdateMessage(byteStream);
                        }
                        break;
                    case TypeBytes.ENTITY_MESSAGE_TYPE_MOVE:
                        if(EntityMessage.canParseMessage(byteStream,secondByte)){
                            rVal = EntityMessage.parseMoveMessage(byteStream);
                        }
                        break;
                    case TypeBytes.ENTITY_MESSAGE_TYPE_DESTROY:
                        if(EntityMessage.canParseMessage(byteStream,secondByte)){
                            rVal = EntityMessage.parseDestroyMessage(byteStream);
                        }
                        break;
                    case TypeBytes.ENTITY_MESSAGE_TYPE_SETBEHAVIORTREE:
                        if(EntityMessage.canParseMessage(byteStream,secondByte)){
                            rVal = EntityMessage.parseSetBehaviorTreeMessage(byteStream);
                        }
                        break;
                    case TypeBytes.ENTITY_MESSAGE_TYPE_SETPROPERTY:
                        if(EntityMessage.canParseMessage(byteStream,secondByte)){
                            rVal = EntityMessage.parsesetPropertyMessage(byteStream);
                        }
                        break;
                    case TypeBytes.ENTITY_MESSAGE_TYPE_ATTACHENTITYTOENTITY:
                        if(EntityMessage.canParseMessage(byteStream,secondByte)){
                            rVal = EntityMessage.parseattachEntityToEntityMessage(byteStream);
                        }
                        break;
                }
                break;
            }
        }
        return rVal;
    }
    
    public boolean isSerialized(){
        return serialized;
    }
    
    abstract void serialize();
    
}

