package electrosphere.net.parser.net.message;

import io.github.studiorailgun.CircularByteBuffer;
import electrosphere.net.parser.util.ByteStreamUtils;
import java.util.LinkedList;
import java.util.List;

public class LoreMessage extends NetworkMessage {

    /**
     * The types of messages available in this category.
     */
    public enum LoreMessageType {
        REQUESTRACES,
        RESPONSERACES,
    }

    /**
     * The type of this message in particular.
     */
    LoreMessageType messageType;
    String data;

    /**
     * Constructor
     * @param messageType The type of this message
     */
    private LoreMessage(LoreMessageType messageType){
        this.type = MessageType.LORE_MESSAGE;
        this.messageType = messageType;
    }

    /**
     * Constructor
     */
    protected LoreMessage(){
        this.type = MessageType.LORE_MESSAGE;
    }

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

    /**
     * Gets data
     */
    public String getdata() {
        return data;
    }

    /**
     * Sets data
     */
    public void setdata(String data) {
        this.data = data;
    }

    /**
     * Removes the packet header from the buffer
     * @param byteBuffer The buffer
     */
    static void stripPacketHeader(CircularByteBuffer byteBuffer){
        byteBuffer.read(2);
    }

    /**
     * Checks if this message can be parsed (ie are all bytes present)
     * @param byteBuffer The buffer
     * @param secondByte The second byte, signifying the subtype of the message
     * @return true if the message can be parsed, false otherwise
     */
    public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
        switch(secondByte){
            case TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACES:
                if(byteBuffer.getRemaining() >= TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACES_SIZE){
                    return true;
                } else {
                    return false;
                }
            case TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACES:
                return LoreMessage.canParseResponseRacesMessage(byteBuffer);
        }
        return false;
    }

    /**
     * Parses a message of type RequestRaces
     */
    public static LoreMessage parseRequestRacesMessage(CircularByteBuffer byteBuffer, MessagePool pool){
        LoreMessage rVal = (LoreMessage)pool.get(MessageType.LORE_MESSAGE);
        rVal.messageType = LoreMessageType.REQUESTRACES;
        LoreMessage.stripPacketHeader(byteBuffer);
        return rVal;
    }

    /**
     * Constructs a message of type RequestRaces
     */
    public static LoreMessage constructRequestRacesMessage(){
        LoreMessage rVal = new LoreMessage(LoreMessageType.REQUESTRACES);
        rVal.serialize();
        return rVal;
    }

    /**
     * Checks if a message of type ResponseRaces can be parsed from the byte stream
     */
    public static boolean canParseResponseRacesMessage(CircularByteBuffer byteBuffer){
        int currentStreamLength = byteBuffer.getRemaining();
        List<Byte> temporaryByteQueue = new LinkedList<Byte>();
        int dataSize = 0;
        if(currentStreamLength < 6){
            return false;
        } else {
            temporaryByteQueue.add(byteBuffer.peek(2 + 0));
            temporaryByteQueue.add(byteBuffer.peek(2 + 1));
            temporaryByteQueue.add(byteBuffer.peek(2 + 2));
            temporaryByteQueue.add(byteBuffer.peek(2 + 3));
            dataSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
        }
        if(currentStreamLength < 6 + dataSize){
            return false;
        }
        return true;
    }

    /**
     * Parses a message of type ResponseRaces
     */
    public static LoreMessage parseResponseRacesMessage(CircularByteBuffer byteBuffer, MessagePool pool){
        LoreMessage rVal = (LoreMessage)pool.get(MessageType.LORE_MESSAGE);
        rVal.messageType = LoreMessageType.RESPONSERACES;
        LoreMessage.stripPacketHeader(byteBuffer);
        rVal.setdata(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
        return rVal;
    }

    /**
     * Constructs a message of type ResponseRaces
     */
    public static LoreMessage constructResponseRacesMessage(String data){
        LoreMessage rVal = new LoreMessage(LoreMessageType.RESPONSERACES);
        rVal.setdata(data);
        rVal.serialize();
        return rVal;
    }

    @Override
    void serialize(){
        byte[] intValues = new byte[8];
        byte[] stringBytes;
        switch(this.messageType){
            case REQUESTRACES:
                rawBytes = new byte[2];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_LORE;
                //entity messaage header
                rawBytes[1] = TypeBytes.LORE_MESSAGE_TYPE_REQUESTRACES;
                break;
            case RESPONSERACES:
                rawBytes = new byte[2+4+data.length()];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_LORE;
                //entity messaage header
                rawBytes[1] = TypeBytes.LORE_MESSAGE_TYPE_RESPONSERACES;
                intValues = ByteStreamUtils.serializeIntToBytes(data.length());
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                stringBytes = data.getBytes();
                for(int i = 0; i < data.length(); i++){
                    rawBytes[6+i] = stringBytes[i];
                }
                break;
        }
        serialized = true;
    }

}
