#include "pqmsgheader.h"

namespace PQ {

MSGRead::MSGRead(bool errorContine, QObject * parent):QObject(parent),
    _errorContine(errorContine),_status(0),_bytePos(0),_needBytes(0)
{}


bool MSGRead::readMsg(const QByteArray data)
{
    const int max = data.length();
    int pos = 0;
    while(pos < max){
        const char byte = data.at(pos);
        switch (_status) {
        case 0:
        {
            if(byte == 'P'){
                _status ++;
            } else {
                emit hasError();
                if(!_errorContine) return false;
            }
            ++pos;
        }
            break;
        case 1:
        { // Q
            if(byte == 'Q'){
                _status ++;
                _bytePos = 0;
                pos ++;
            } else {
                _status = 0;
                emit hasError();
                if(!_errorContine) return false;
            }

        }
            break;
        case 2:
        {
            if(readHeaderCloum(byte,4)){
                header.msgID = qFromBigEndian<uint>(reinterpret_cast<uchar *>(&byteBuffer[0]));
                _bytePos = 0;
                _status ++;
            }
            pos ++;
        }
            break;
        case 3:
        {
            if(readHeaderCloum(byte,2)){
                header.msgType = qFromBigEndian<ushort>(reinterpret_cast<uchar *>(&byteBuffer[0]));
                _bytePos = 0;
                _status ++;
            }
            pos ++;
        }
            break;
        case 4:
        {
            if(readHeaderCloum(byte,4)){
                header.length = qFromBigEndian<uint>(reinterpret_cast<uchar *>(&byteBuffer[0]));
                _bytePos = 0;
                _status ++;
            }
            pos ++;
        }
            break;
        case 5:{
            header.compress = byte;
            _status ++;
            pos ++;
        }
            break;
        case 6:{
            header.encrypt = byte;
            _status ++;
            pos ++;
        }
            break;
        case 7:
        {
            if(byte == 'p'){
                _status ++;
                pos ++;
            } else {
                _status = 0;
                emit hasError();
                if(!_errorContine) return false;
            }
        }
            break;
        case 8:
        {
            if(byte == 'q'){
                pos ++;
                _bytePos = 0;
                _needBytes = header.length;
                body.clear();
                if(header.length > 0){
                    _status ++;
                } else {
                    _status = 0;
                    emit revicedMSG(header,body);
                }
            } else {
                _status = 0;
                emit hasError();
                if(!_errorContine) return false;
            }
        }
            break;
        case 9:{
            if(readData(data,pos,max)){
                _status = 0;
                emit revicedMSG(header, body);
                body.clear();
            }
        }
        default:
            _status = 0;
            break;
        }
    }
    return true;
}

 bool MSGRead::readData(const QByteArray & data,int & pos, int max)
 {
     const int canRead = max - pos;
     if(canRead >= _needBytes){
         body.append(data.mid(pos,_needBytes));
         pos += _needBytes;
         _needBytes -= 0;
         return true;
     } else {
         body.append(data.mid(pos,canRead));
         pos += canRead;
         _needBytes -= canRead;
         return false;
     }
 }


}
