package electrosphere.net.parser.net.message;

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

public class CombatMessage extends NetworkMessage {

    public enum CombatMessageType {
        SERVERREPORTHITBOXCOLLISION,
    }

    CombatMessageType messageType;
    int entityID;
    int receiverEntityID;
    double positionX;
    double positionY;
    double positionZ;
    double rotationX;
    double rotationY;
    double rotationZ;
    double rotationW;
    long time;
    String hitboxType;
    String hurtboxType;

    CombatMessage(CombatMessageType messageType){
        this.type = MessageType.COMBAT_MESSAGE;
        this.messageType = messageType;
    }

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

    public int getentityID() {
        return entityID;
    }

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

    public int getreceiverEntityID() {
        return receiverEntityID;
    }

    public void setreceiverEntityID(int receiverEntityID) {
        this.receiverEntityID = receiverEntityID;
    }

    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 double getrotationX() {
        return rotationX;
    }

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

    public double getrotationY() {
        return rotationY;
    }

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

    public double getrotationZ() {
        return rotationZ;
    }

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

    public double getrotationW() {
        return rotationW;
    }

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

    public long gettime() {
        return time;
    }

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

    public String gethitboxType() {
        return hitboxType;
    }

    public void sethitboxType(String hitboxType) {
        this.hitboxType = hitboxType;
    }

    public String gethurtboxType() {
        return hurtboxType;
    }

    public void sethurtboxType(String hurtboxType) {
        this.hurtboxType = hurtboxType;
    }

    static void stripPacketHeader(CircularByteBuffer byteBuffer){
        byteBuffer.read(2);
    }

    public static boolean canParseMessage(CircularByteBuffer byteBuffer, byte secondByte){
        switch(secondByte){
            case TypeBytes.COMBAT_MESSAGE_TYPE_SERVERREPORTHITBOXCOLLISION:
                return CombatMessage.canParseserverReportHitboxCollisionMessage(byteBuffer);
        }
        return false;
    }

    public static boolean canParseserverReportHitboxCollisionMessage(CircularByteBuffer byteBuffer){
        int currentStreamLength = byteBuffer.getRemaining();
        List<Byte> temporaryByteQueue = new LinkedList<Byte>();
        if(currentStreamLength < 6){
            return false;
        }
        if(currentStreamLength < 10){
            return false;
        }
        if(currentStreamLength < 18){
            return false;
        }
        int hitboxTypeSize = 0;
        if(currentStreamLength < 22){
            return false;
        } else {
            temporaryByteQueue.add(byteBuffer.peek(18 + 0));
            temporaryByteQueue.add(byteBuffer.peek(18 + 1));
            temporaryByteQueue.add(byteBuffer.peek(18 + 2));
            temporaryByteQueue.add(byteBuffer.peek(18 + 3));
            hitboxTypeSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
        }
        if(currentStreamLength < 22 + hitboxTypeSize){
            return false;
        }
        int hurtboxTypeSize = 0;
        if(currentStreamLength < 26){
            return false;
        } else {
            temporaryByteQueue.add(byteBuffer.peek(22 + hitboxTypeSize + 0));
            temporaryByteQueue.add(byteBuffer.peek(22 + hitboxTypeSize + 1));
            temporaryByteQueue.add(byteBuffer.peek(22 + hitboxTypeSize + 2));
            temporaryByteQueue.add(byteBuffer.peek(22 + hitboxTypeSize + 3));
            hurtboxTypeSize = ByteStreamUtils.popIntFromByteQueue(temporaryByteQueue);
        }
        if(currentStreamLength < 26 + hitboxTypeSize + hurtboxTypeSize){
            return false;
        }
        return true;
    }

    public static CombatMessage parseserverReportHitboxCollisionMessage(CircularByteBuffer byteBuffer){
        CombatMessage rVal = new CombatMessage(CombatMessageType.SERVERREPORTHITBOXCOLLISION);
        stripPacketHeader(byteBuffer);
        rVal.setentityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.setreceiverEntityID(ByteStreamUtils.popIntFromByteQueue(byteBuffer));
        rVal.settime(ByteStreamUtils.popLongFromByteQueue(byteBuffer));
        rVal.sethitboxType(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
        rVal.sethurtboxType(ByteStreamUtils.popStringFromByteQueue(byteBuffer));
        return rVal;
    }

    public static CombatMessage constructserverReportHitboxCollisionMessage(int entityID,int receiverEntityID,long time,String hitboxType,String hurtboxType){
        CombatMessage rVal = new CombatMessage(CombatMessageType.SERVERREPORTHITBOXCOLLISION);
        rVal.setentityID(entityID);
        rVal.setreceiverEntityID(receiverEntityID);
        rVal.settime(time);
        rVal.sethitboxType(hitboxType);
        rVal.sethurtboxType(hurtboxType);
        rVal.serialize();
        return rVal;
    }

    @Override
    void serialize(){
        byte[] intValues = new byte[8];
        byte[] stringBytes;
        switch(this.messageType){
            case SERVERREPORTHITBOXCOLLISION:
                rawBytes = new byte[2+4+4+8+4+hitboxType.length()+4+hurtboxType.length()];
                //message header
                rawBytes[0] = TypeBytes.MESSAGE_TYPE_COMBAT;
                //entity messaage header
                rawBytes[1] = TypeBytes.COMBAT_MESSAGE_TYPE_SERVERREPORTHITBOXCOLLISION;
                intValues = ByteStreamUtils.serializeIntToBytes(entityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[2+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(receiverEntityID);
                for(int i = 0; i < 4; i++){
                    rawBytes[6+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeLongToBytes(time);
                for(int i = 0; i < 8; i++){
                    rawBytes[10+i] = intValues[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(hitboxType.length());
                for(int i = 0; i < 4; i++){
                    rawBytes[18+i] = intValues[i];
                }
                stringBytes = hitboxType.getBytes();
                for(int i = 0; i < hitboxType.length(); i++){
                    rawBytes[22+i] = stringBytes[i];
                }
                intValues = ByteStreamUtils.serializeIntToBytes(hurtboxType.length());
                for(int i = 0; i < 4; i++){
                    rawBytes[22+hitboxType.length()+i] = intValues[i];
                }
                stringBytes = hurtboxType.getBytes();
                for(int i = 0; i < hurtboxType.length(); i++){
                    rawBytes[26+hitboxType.length()+i] = stringBytes[i];
                }
                break;
        }
        serialized = true;
    }

}
