#include "codecxyckanalog.h"


CODECXyckAnalog::CODECXyckAnalog()
    :QObject()
{
    _dataList=new QList<MyoelectricData>();
    iii=0;
    logFile=new QFile("d:/test.txt");
    logFile->open(QIODevice::Truncate|QIODevice::ReadWrite);
    qDebug()<<"build";
}

QByteArray CODECXyckAnalog::reqSetting(int iChannel, AnalogSetting setting)
{
    QByteArray buffer;
    buffer.append(static_cast<char>(FUNCCODE_ANALOG_SETTING));
    buffer.append(static_cast<char>(iChannel));
    buffer.append(static_cast<char>(setting.workmode));
    buffer.append(static_cast<char>(setting.samplerate>>8));
    buffer.append(static_cast<char>(setting.samplerate%0x100));
    buffer.append(static_cast<char>(static_cast<int>(setting.frequency*2)>>8));
    buffer.append(static_cast<char>(static_cast<int>(setting.frequency*2)%0x100));
    buffer.append(static_cast<char>(setting.pulseWidth>>8));
    buffer.append(static_cast<char>(setting.pulseWidth%0x100));
    buffer.append(static_cast<char>(static_cast<int>(setting.risingTime*2)>>8));
    buffer.append(static_cast<char>(static_cast<int>(setting.risingTime*2)%0x100));
    buffer.append(static_cast<char>(setting.holdingTime>>8));
    buffer.append(static_cast<char>(setting.holdingTime%0x100));
    buffer.append(static_cast<char>(static_cast<int>(setting.fallingTime*2)>>8));
    buffer.append(static_cast<char>(static_cast<int>(setting.fallingTime*2)%0x100));
    buffer.append(static_cast<char>(setting.breakTime>>8));
    buffer.append(static_cast<char>(setting.breakTime%0x100));
    return  createFrame(buffer);
}

QByteArray CODECXyckAnalog::reqChannalControl(ChannelState ch1, ChannelState ch2, ChannelState ch3, ChannelState ch4)
{
    QByteArray buffer;
    buffer.append(static_cast<char>(FUNCCODE_ANALOG_CHANNAL_CONTROL));
    buffer.append(static_cast<char>(ch1));
    buffer.append(static_cast<char>(ch2));
    buffer.append(static_cast<char>(ch3));
    buffer.append(static_cast<char>(ch4));
    return createFrame(buffer);
}

QByteArray CODECXyckAnalog::reqSetCurrent(int iChannel, int iCurrent)
{
    if(iCurrent>100||iCurrent<0)
    {
        return  nullptr;
    }
    QByteArray buffer;
    buffer.append(static_cast<char>(FUNCCODE_ANALOG_SET_CURRENT));
    buffer.append(static_cast<char>(iChannel));
    buffer.append(static_cast<char>(iCurrent));
    return createFrame(buffer);
}

QByteArray CODECXyckAnalog::reqDataChange(int iChannel, DataMode datamode)
{
    QByteArray buffer;
    buffer.append(static_cast<char>(FUNCCODE_ANALOG_DATA_CHANGE));
    buffer.append(static_cast<char>(iChannel));
    buffer.append(static_cast<char>(datamode));
    return createFrame(buffer);
}

QByteArray CODECXyckAnalog::reqSetGain(int iChannel, GainMode gainmode)
{
    QByteArray buffer;
    buffer.append(static_cast<char>(FUNCCODE_ANALOG_SET_GAIN));
    buffer.append(static_cast<char>(iChannel));
    buffer.append(static_cast<char>(gainmode));
    return  createFrame(buffer);
}

QByteArray CODECXyckAnalog::reqSetCollect(int iChannel, ChannelState channelstate)
{
    QByteArray buffer;
    buffer.append(static_cast<char>(FUNCCODE_ANALOG_SET_COLLECT));
    buffer.append(static_cast<char>(iChannel));
    buffer.append(static_cast<char>(channelstate));
    return createFrame(buffer);
}

QByteArray CODECXyckAnalog::reqSetStimulate(int iChannel, ChannelState channelstate)
{
    QByteArray buffer;
    buffer.append(static_cast<char>(FUNCCODE_ANALOG_SET_STIMULATE));
    buffer.append(static_cast<char>(iChannel));
    buffer.append(static_cast<char>(channelstate));
    return createFrame(buffer);
}

QByteArray CODECXyckAnalog::reqGetState()
{
    QByteArray buffer;
    buffer.append(static_cast<char>(FUNCCODE_ANALOG_STATE));
    buffer.append(static_cast<char>(0));
    buffer.append(static_cast<char>(0));
    return createFrame(buffer);
}



void CODECXyckAnalog::dealFrame(QByteArray buffer)
{
    switch (static_cast<uint8_t>(buffer.data()[2]))
    {
    case FUNCCODE_ANALOG_SETTING:
        respSetting(buffer);
        break;
    case FUNCCODE_ANALOG_CHANNAL_CONTROL:
        respChannalControl(buffer);
        break;
    case FUNCCODE_ANALOG_SET_CURRENT:
        respSetCurrent(buffer);
        break;
    case FUNCCODE_ANALOG_DATA_UPLOAD:
        respDataUpload(buffer);
        break;
    case FUNCCODE_ANALOG_DATA_CHANGE:
        respDataChange(buffer);
        break;
    case FUNCCODE_ANALOG_SET_GAIN:
        respSetGain(buffer);
        break;
    case FUNCCODE_ANALOG_SET_COLLECT:
        respSetCollect(buffer);
        break;
    case FUNCCODE_ANALOG_SET_STIMULATE:
        respSetStimulate(buffer);
        break;
    case FUNCCODE_ANALOG_STATE:
        respGetState(buffer);
        break;
    case FUNCCODE_ANALOG_ERROR:
        emit commandSendError(static_cast<uint8_t>(buffer.data()[3])
                ,ErrorCode(static_cast<uint8_t>(buffer.data()[4]))
                ,static_cast<uint8_t>(buffer.data()[5]));
        break;
    default:
        break;
    }
}

void CODECXyckAnalog::clearList()
{
    _dataList->clear();
}



QList<MyoelectricData> *CODECXyckAnalog::GetMyoelectricData(int iStep)
{

    int iCount=_dataList->length();

    if(iCount<=0)
    {
        return nullptr;
    }

    int iDT=0;
    if(iStep<=iCount&&iStep!=0)
    {
        iDT=iCount/iStep;
    }
    if(iDT<1)
    {
        iDT=0;
    }
    QList<MyoelectricData> *resultList=new QList<MyoelectricData>();
    for(int i=0;i<iCount;)
    {
        resultList->append(_dataList->takeFirst());
        i++;
        if(resultList->count()==iStep)
        {
            break;
        }
        for(int j=0;j<iDT&&i<iCount;j++)
        {
            _dataList->takeFirst();
            i++;
        }
    }
    return  resultList;
}

QByteArray CODECXyckAnalog::respAnalogState(AnalogState *as)
{
    QByteArray buffer;
    buffer.append(static_cast<char>(FUNCCODE_ANALOG_STATE));
    buffer.append(static_cast<char>(0x00));
    buffer.append(static_cast<char>(as->electrodeStateA));
    buffer.append(static_cast<char>(as->electrodeStateB));
    buffer.append(static_cast<char>(as->electrodeStateC));
    buffer.append(static_cast<char>(as->electrodeStateD));
    buffer.append(static_cast<char>(as->resetState));
    buffer.append(static_cast<char>(as->channelWorkStateA));
    buffer.append(static_cast<char>(as->channelWorkStateB));
    buffer.append(static_cast<char>(as->channelWorkStateC));
    buffer.append(static_cast<char>(as->channelWorkStateD));

    buffer.append(static_cast<char>(as->AValueA));
    buffer.append(static_cast<char>(as->AValueB));
    buffer.append(static_cast<char>(as->AValueC));
    buffer.append(static_cast<char>(as->AValueD));
    return createFrame(buffer);
}

QByteArray CODECXyckAnalog::respMyoelectricData(MyoelectricData *md)
{
    QByteArray buffer;
    buffer.append(static_cast<char>(FUNCCODE_ANALOG_DATA_UPLOAD));
    buffer.append(static_cast<char>(0x00));
    buffer.append(static_cast<char>(md->ch1>>8));
    buffer.append(static_cast<char>(md->ch1%0x100));
    buffer.append(static_cast<char>(md->ch2>>8));
    buffer.append(static_cast<char>(md->ch2%0x100));
    buffer.append(static_cast<char>(md->ch3>>8));
    buffer.append(static_cast<char>(md->ch3%0x100));
    buffer.append(static_cast<char>(md->ch4>>8));
    buffer.append(static_cast<char>(md->ch4%0x100));
    return createFrame(buffer);
}

void CODECXyckAnalog::respSetting(QByteArray buffer)
{
    int iChannel=buffer.data()[3];
    AnalogSetting *analogSetting=new AnalogSetting();
    analogSetting->workmode =WorkMode(static_cast<uint8_t>(buffer.data()[4]));
    analogSetting->samplerate=SampleRate((static_cast<uint8_t>(buffer.data()[5])<<8)+static_cast<uint8_t>(buffer.data()[6]));
    analogSetting->frequency = ((static_cast<uint8_t>(buffer.data()[7])<<8)+static_cast<uint8_t>(buffer.data()[8]))/2.0;
    analogSetting->pulseWidth  =(static_cast<uint8_t>(buffer.data()[9])<<8)+static_cast<uint8_t>(buffer.data()[10]);
    analogSetting->risingTime= ((static_cast<uint8_t>(buffer.data()[11])<<8)+static_cast<uint8_t>(buffer.data()[12]))/2.0;
    analogSetting->holdingTime =(static_cast<uint8_t>(buffer.data()[13])<<8)+static_cast<uint8_t>(buffer.data()[14]);
    analogSetting->fallingTime=((static_cast<uint8_t>(buffer.data()[15])<<8)+static_cast<uint8_t>(buffer.data()[16]))/2.0;
    analogSetting->breakTime   =(static_cast<uint8_t>(buffer.data()[17])<<8)+static_cast<uint8_t>(buffer.data()[18]);
    emit analogSettingRev(iChannel,analogSetting);
}

void CODECXyckAnalog::respChannalControl(QByteArray buffer)
{
    ChannelState ch1=ChannelState(static_cast<uint8_t>(buffer.data()[3]));
    ChannelState ch2=ChannelState(static_cast<uint8_t>(buffer.data()[4]));
    ChannelState ch3=ChannelState(static_cast<uint8_t>(buffer.data()[5]));
    ChannelState ch4=ChannelState(static_cast<uint8_t>(buffer.data()[6]));
    emit channalControlRev(ch1,ch2,ch3,ch4);
}

void CODECXyckAnalog::respSetCurrent(QByteArray buffer)
{
    int iChannel=buffer.data()[3];
    int iCurrent=static_cast<uint8_t>(buffer.data()[4]);
    emit currentRev(iChannel,iCurrent);
}

void CODECXyckAnalog::respDataUpload(QByteArray buffer)
{
    ignoreCount++;

    MyoelectricData md;
    md.ch1=(static_cast<uint8_t>(buffer.data()[4])<<8)+static_cast<uint8_t>(buffer.data()[5]);
    md.ch2=(static_cast<uint8_t>(buffer.data()[6])<<8)+static_cast<uint8_t>(buffer.data()[7]);
    md.ch3=(static_cast<uint8_t>(buffer.data()[8])<<8)+static_cast<uint8_t>(buffer.data()[9]);
    md.ch4=(static_cast<uint8_t>(buffer.data()[10])<<8)+static_cast<uint8_t>(buffer.data()[11]);
    QString logTemp=QString::number(md.ch1)+" "+QString::number(md.ch2)+" "+QString::number(md.ch3)+" "+QString::number(md.ch4)+"\r\n";
    logFile->write(logTemp.toUtf8());
    logFile->flush();
    //    if(ignoreCount%100==0)
//    {
//        qDebug()<<QString::number(ignoreCount);
//        qDebug()<<"ch1:"<<QString::number(md.ch1)<<"ch2:"<<QString::number(md.ch2)<<"ch3:"<<QString::number(md.ch3)<<"ch4:"<<QString::number(md.ch4);
//    }
    _dataList->append(md);


    //qDebug()<<QString::number(md.ch1);
}

void CODECXyckAnalog::respDataChange(QByteArray buffer)
{
    int iChannel=static_cast<uint8_t>(buffer.data()[3]);
    DataMode dm=DataMode(static_cast<uint8_t>(buffer.data()[4]));
    ignoreCount=0;
    emit dataChangeRev(iChannel,dm);
}

void CODECXyckAnalog::respSetGain(QByteArray buffer)
{
    int iChannel=static_cast<uint8_t>(buffer.data()[3]);
    GainMode gm=GainMode(static_cast<uint8_t>(buffer.data()[4]));
    emit gainRev(iChannel,gm);
}

void CODECXyckAnalog::respSetCollect(QByteArray buffer)
{
    int iChannel=static_cast<uint8_t>(buffer.data()[3]);
    ChannelState cs=ChannelState(static_cast<uint8_t>(buffer.data()[4]));
    emit collectRev(iChannel,cs);
}

void CODECXyckAnalog::respSetStimulate(QByteArray buffer)
{
    int iChannel=static_cast<uint8_t>(buffer.data()[3]);
    ChannelState cs=ChannelState(static_cast<uint8_t>(buffer.data()[4]));
    emit stimulateRev(iChannel,cs);
}

void CODECXyckAnalog::respGetState(QByteArray buffer)
{
    AnalogState *analogstate = new AnalogState();
    analogstate->electrodeStateA=ModeState(static_cast<uint8_t>(buffer.data()[4]));
    analogstate->electrodeStateB=ModeState(static_cast<uint8_t>(buffer.data()[5]));
    analogstate->electrodeStateC=ModeState(static_cast<uint8_t>(buffer.data()[6]));
    analogstate->electrodeStateD=ModeState(static_cast<uint8_t>(buffer.data()[7]));
    analogstate->resetState=ModeState(static_cast<uint8_t>(buffer.data()[8]));
    analogstate->channelWorkStateA=ChannelWorkState(static_cast<uint8_t>(buffer.data()[9]));
    analogstate->channelWorkStateB=ChannelWorkState(static_cast<uint8_t>(buffer.data()[10]));
    analogstate->channelWorkStateC=ChannelWorkState(static_cast<uint8_t>(buffer.data()[11]));
    analogstate->channelWorkStateD=ChannelWorkState(static_cast<uint8_t>(buffer.data()[12]));
    analogstate->AValueA=static_cast<uint8_t>(buffer.data()[13]);
    analogstate->AValueB=static_cast<uint8_t>(buffer.data()[14]);
    analogstate->AValueC=static_cast<uint8_t>(buffer.data()[15]);
    analogstate->AValueD=static_cast<uint8_t>(buffer.data()[16]);
    emit stateInfoRev(analogstate);


}

QByteArray CODECXyckAnalog::createFrame(QByteArray dataBuffer)
{
    QByteArray buffer;
    buffer.append(static_cast<char>(FRAME_HEAD));
    buffer.append(static_cast<char>(dataBuffer.length()));
    for(int i=0;i<dataBuffer.length();i++)
    {
        buffer.append(dataBuffer.data()[i]);
    }
    buffer.append(DataCheck::getSum(buffer,2,buffer.length()-1));
    buffer.append(0x55);
    return  buffer;
}