#include "serialequipment.h"

SerialEquipment::SerialEquipment()
{
    _isLog=false;
    this->_serialPort=new QSerialPort();
    connect(this->_serialPort,SIGNAL(readyRead()),this,SLOT(dataReceive()));
    _mutex=new QMutex(QMutex::Recursive);
}

SerialEquipment::SerialEquipment(QString portName,QSerialPort::BaudRate baunRate,QSerialPort::DataBits dataBits,QSerialPort::Parity parity,QSerialPort::StopBits stopBits,int readBufferSize)
{
    _isLog=false;
    this->setSerialInfo(portName,baunRate,dataBits,parity,stopBits,readBufferSize);
    this->_serialPort=new QSerialPort();
    connect(this->_serialPort,SIGNAL(readyRead()),this,SLOT(dataReceive()));
    _mutex=new QMutex(QMutex::Recursive);
}

SerialEquipment::SerialEquipment(QString portName)
{
    _isLog=false;
    this->setSerialInfo(portName,QSerialPort::Baud460800,QSerialPort::Data8,QSerialPort::NoParity,QSerialPort::OneStop,30);
    this->_serialPort=new QSerialPort();
    connect(this->_serialPort,SIGNAL(readyRead()),this,SLOT(dataReceive()));
    _mutex=new QMutex(QMutex::Recursive);
}

SerialEquipment::SerialEquipment(QString portName, QSerialPort::BaudRate baunRate)
{
    _isLog=false;
    this->setSerialInfo(portName,baunRate,QSerialPort::Data8,QSerialPort::NoParity,QSerialPort::OneStop,30);
    this->_serialPort=new QSerialPort();
    connect(this->_serialPort,SIGNAL(readyRead()),this,SLOT(dataReceive()));
    _mutex=new QMutex(QMutex::Recursive);
}

SerialEquipment::~SerialEquipment()
{
    closePort();
    delete this->_serialPort;
}

void SerialEquipment::setSerialInfo(QString portName, QSerialPort::BaudRate baunRate, QSerialPort::DataBits dataBits, QSerialPort::Parity parity, QSerialPort::StopBits stopBits, int readBufferSize)
{
    _isLog=false;
    this->_strPortName=portName;
    this->_iBaudRate=baunRate;
    this->_iDataBits=dataBits;
    this->_iParity=parity;
    this->_iStopBits=stopBits;
    this->_iReadBufferSize=readBufferSize;
    this->needWait=true;

}

void SerialEquipment::setSerialInfo(QString portName, QSerialPort::BaudRate baunRate)
{

    setSerialInfo(portName,baunRate,QSerialPort::Data8,QSerialPort::NoParity,QSerialPort::OneStop,512);
}

bool SerialEquipment::getPortState()
{
    if(this->_serialPort==nullptr)
    {
        return false;
    }
    else
    {
        if(this->_serialPort->isOpen())
        {
            return true ;
        }
        else
        {
            return false;
        }
    }
}

bool SerialEquipment::openPort()
{
    _isLog=false;
    testJDCount=0;
    testTotalCount=0;
    bTestDebug=false;
    if(this->_serialPort==nullptr)
    {
        return false;
    }
    else
    {
        if(!this->_serialPort->isOpen())
        {
            this->_serialPort->setPortName(this->_strPortName);
            this->_serialPort->setBaudRate(this->_iBaudRate);
            this->_serialPort->setParity(this->_iParity);
            this->_serialPort->setStopBits(this->_iStopBits);
            this->_serialPort->setDataBits(this->_iDataBits);
            this->_serialPort->setFlowControl(QSerialPort::NoFlowControl);
            this->_serialPort->setReadBufferSize(512);
            bool bresult=this->_serialPort->open(QIODevice::ReadWrite);
            return bresult;
        }
        else
        {
            return false;
        }
    }
}

bool SerialEquipment::closePort()
{
    if(this->_serialPort==nullptr)
    {
        return false;
    }
    else
    {
        if(this->_serialPort->isOpen())
        {
            this->_serialPort->close();
            return true;
        }
        else
        {
            return false;
        }
    }
}

void SerialEquipment::dataReceive()
{
    QByteArray revBuffer;
    int iHeadLength=this->_frameHead.length();
    int iTailLength=this->_frameTail.length();
    while(this->_serialPort->bytesAvailable()>0)
    {
        revBuffer.clear();
        revBuffer=this->_serialPort->readAll();
        //this->testTotalCount+=revBuffer.count();
        //        if(bTestDebug)
        //        {
        //qDebug()<<"rev All: "<<tool::ByteArray2HEXQString(revBuffer);
        //        }
        //
        emit onDataReceived(&revBuffer);
        if(iHeadLength==0||iTailLength==0)
        {
            return;
        }
        int iLen=revBuffer.length();
        if(_isLog)
        {
            _logInfo->iRevTotalByte+=iLen;

        }
        int iCount=0;
        while(iCount<iLen)
        {
            //qDebug()<<"tempArrayCount"<<_tempArray.count();
            if(_tempArray.length()==iHeadLength)
            {
                if(!tool::checkArraySame(this->_frameHead,_tempArray,iHeadLength-1,0))
                {
                    _tempArray.remove(0,1);
                }
            }
            _tempArray.append(revBuffer.data()[iCount]);
            if(_tempArray.length()==iHeadLength+1)
            {
                this->_iFrameSize= static_cast<uint8_t>(revBuffer.data()[iCount])+iHeadLength+iTailLength+2;
                if(this->_iFrameSize>30){
                    qDebug()<<"lastBag:"<<tool::ByteArray2HEXQString(_tempArray);
                    _tempArray.clear();
                    continue;
                }
                //qDebug()<<"_iFrameSize"<<this->_iFrameSize;
            }
            iCount++;
            if(_tempArray.length()==this->_iFrameSize)
            {
                if(this->_iFrameSize>30){
                    qDebug()<<"lastBag:"<<tool::ByteArray2HEXQString(_tempArray);

                }
                QByteArray frameArray=_tempArray;
                //                if(bTestDebug)
                //                {
                //                if(frameArray.at(2)==static_cast<char>(0x94)){
                //                    qDebug()<<QString::number(this->_iFrameSize)+"wait check: "<<tool::ByteArray2HEXQString(frameArray);
                //                }
                //                }
                if(tool::checkArraySame(frameArray,_frameTail,frameArray.length()-iTailLength,frameArray.length()-1)
                        && checkData(frameArray,iTailLength))
                {
                    //                    if(bTestDebug)
                    //                    {
                    //                        qDebug()<<"check:true ";
                    //                    }
                    emit this->onFrameReceived(&frameArray);
                    //                    if(frameArray[2]!= 0x94)
                    //                    {
                    //                        testJDCount++;
                    //                    }
                    dealDate(frameArray);
                    if(_isLog)
                    {
                        _logInfo->iGoodFrameCount++;
                        _logInfo->iRevGoodByte+=frameArray.count();
                        if(static_cast<uint8_t>(frameArray.data()[2])==0x8F||static_cast<uint8_t>(frameArray.data()[2])==0x9F)
                        {
                            _logInfo->iSendNGFrameCount++;
                        }
                    }
                    _tempArray.clear();
                }
                else
                {
                    qDebug()<<"count:"+QString::number(iCount)+"--error--"<<tool::ByteArray2HEXQString(_tempArray);
                    if(_isLog)
                    {
                        _logInfo->iCheckNGFrameCount++;
                    }
                    //_tempArray=adjustList(_tempArray);
                    _tempArray.clear();
                    //                    //iCount-=_tempArray.count();
                    //                    if(iCount<0){
                    //                        iCount=0;
                    //                    }
                    //qDebug()<<"count:"+QString::number(iCount)+"--back--"<<tool::ByteArray2HEXQString(_tempArray);
                    //_tempArray.clear();
                }
            }
        }
    }
    revBuffer.clear();
}

bool SerialEquipment::checkData(QByteArray buffer, int iTailIndex)
{
    return  DataCheck::sumCheck(buffer,iTailIndex);
}



void SerialEquipment::dataReceive1()
{
    QByteArray revBuffer;
    int iHeadLength=this->_frameHead.length();
    while(this->_serialPort->bytesAvailable()>0)
    {
        revBuffer.clear();
        revBuffer=this->_serialPort->readAll();
        int iLen=revBuffer.length();
        int iCount=0;
        while(iCount<iLen)
        {
            if(_tempArray.length()==iHeadLength)
            {
                if(!tool::checkArraySame(this->_frameHead,_tempArray,iHeadLength-1,0))
                {
                    _tempArray.remove(0,1);
                }
            }
            _tempArray.append(revBuffer.data()[iCount]);
            iCount++;
            if(_tempArray.length()==this->_iFrameSize)
            {
                QByteArray frameArray=_tempArray;
                if(DataCheck::sumCheck(frameArray))
                {
                    emit this->onFrameReceived(&frameArray);
                    _tempArray.clear();
                }
                else
                {
                    _tempArray=adjustList(_tempArray);

                }
            }
        }

    }
    revBuffer.clear();

}

void SerialEquipment::dealDate(QByteArray)
{

}

SerialLogInfo *SerialEquipment::GetLogInfo()
{
    return _logInfo;
}

void SerialEquipment::delayMsec(int mesc)
{
    QTime temp=QTime::currentTime().addMSecs(mesc);
    while(QTime::currentTime()<temp)
    {
        QCoreApplication::processEvents(QEventLoop::AllEvents,100);
    }
}

QList<QString> SerialEquipment::getAllPorts()
{
    QList<QString> resultList;
    QList<QSerialPortInfo> portList = QSerialPortInfo::availablePorts();
    for (int i=0;i<portList.count();i++)
    {
        resultList.append(portList[i].portName());
    }
    return  resultList;
}

void SerialEquipment::setNeedWait(bool value)
{
    needWait = value;
}
QList<char> SerialEquipment::adjustList(QList<char> srcList)
{
    if(srcList.length()>0)
    {
        srcList.removeAt(0);
    }
    else
    {
        return srcList;
    }
    return tool::findHead(srcList,this->_frameHead);
}

QByteArray SerialEquipment::adjustList(QByteArray srcList)
{
    if(srcList.length()>0)
    {
        srcList.remove(0,1);
    }
    else
    {
        return srcList;
    }
    return tool::findHead(srcList,this->_frameHead);
}

bool SerialEquipment::sendMsg(QByteArray sendBuffer)
{
    if(this->getPortState())
    {
        _mutex->lock();
        this->_serialPort->write(sendBuffer);
        if(needWait){
            qDebug()<<"wait";
            if(!this->_serialPort->waitForBytesWritten()){
                _mutex->unlock();
                return  false;
            }
        }

        _mutex->unlock();
        emit onFrameSended(&sendBuffer);
        //        if(sendBuffer.count()>3&&static_cast<u_int8_t>(sendBuffer[2])!=static_cast<u_int8_t>(0x81)&&static_cast<u_int8_t>(sendBuffer[2])!=static_cast<u_int8_t>(0x99)){
        //            QString tempString = tool::ByteArray2HEXQString(sendBuffer);
        //            qDebug()<<"send: "<<tempString;
        //        }
//        if(static_cast<u_int8_t>(sendBuffer[2])==static_cast<u_int8_t>(0x85))
//        {
//            QString tempString = tool::ByteArray2HEXQString(sendBuffer);
//            qDebug()<<"sendDI_A: "<<tempString;
//        }
//        if(static_cast<u_int8_t>(sendBuffer[2])==static_cast<u_int8_t>(0x93))
//        {
//            QString tempString = tool::ByteArray2HEXQString(sendBuffer);
//            qDebug()<<tempString;
//        }
        return true;
    }
    else
    {
        return false;
    }
}

void SerialEquipment::setLogInfo(bool isLog)
{
    isLog=false;
    if(isLog)
    {
        _logInfo=new SerialLogInfo();
        _logInfo->iCheckNGFrameCount=0;
        _logInfo->iGoodFrameCount=0;
        _logInfo->iRevGoodByte=0;
        _logInfo->iRevTotalByte=0;
        _logInfo->iSendNGFrameCount=0;
        _logInfo->iSendFrameCount=0;
    }
    _isLog=isLog;
}

bool SerialEquipment::sendMsg(QString strMessage)
{
    if(this->getPortState())
    {
        QByteArray sendBuffer=strMessage.toLatin1();
        _mutex->lock();
        this->_serialPort->write(sendBuffer);
        if(needWait){
            //qDebug()<<"wait";
            if(!this->_serialPort->waitForBytesWritten()){
                _mutex->unlock();
                return  false;
            }
        }
        _mutex->unlock();
        emit onFrameSended(&sendBuffer);
        if(_isLog)
        {
            _logInfo->iSendFrameCount++;
        }
        qDebug()<<"send: "<<strMessage;
        return true;
    }
    else
    {
        return false;
    }
}

void SerialEquipment::setFrameHead(QByteArray frameHead)
{
    this->_frameHead=frameHead;
}

void SerialEquipment::setFrameTail(QByteArray frameTail)
{
    this->_frameTail=frameTail;
}

void SerialEquipment::setFrameSize(int iFramSize)
{
    this->_iFrameSize=iFramSize;
}