#include "gamedisplaypage.h"
#include "ui_gamedisplaypage.h"
#include "mainwindowpagecontrol.h"
#include <QPropertyAnimation>
#include <QButtonGroup>
#include <QDebug>
#include <QPaintEvent>
#include <QPainter>
#include "icemodule.h"
#include "ccommunicateapi.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include "currentuserdata.h"
#include "paramtipsdialog.h"
#include "gamecontrol.h"
#include "languagemanager.h"
#include <QMessageBox>
#define SpeedMax 100
#define SleepTime 500
GameDisplayPage::GameDisplayPage(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::GameDisplayPage),
    m_openState(true),
    upDirection(1),
    downDirection(1),
    m_spasmTipsDialog(NULL),
    heartTimer(NULL),
    countDownTimer(NULL),
    m_spasmTimes(0),
    m_currentMode(0),
    m_reportDialog(NULL),
    m_quitDialog(NULL),
    m_emergencyDialog(NULL),
    heartCount(0),
    E_gameState(STOP)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::FramelessWindowHint);      //设置无边框
    setAttribute(Qt::WA_TranslucentBackground,true);    //设置透明
    m_leftAnimation = new QPropertyAnimation(ui->leftPage_GroupBox,"pos");
    m_rightAnimation = new QPropertyAnimation(ui->rightPage_GroupBox,"pos");
    m_leftAnimation->setDuration(1000);
    m_rightAnimation->setDuration(1000);

    QButtonGroup *upLimpGroup = new QButtonGroup(this);
    upLimpGroup->addButton(ui->forward_Btn);
    upLimpGroup->addButton(ui->backward_Btn);

    m_channelBList.append(ui->channelB1_Label);
    m_channelBList.append(ui->channelB2_Label);
    m_channelBList.append(ui->channelB3_Label);
    m_channelBList.append(ui->channelB4_Label);
    m_channelBList.append(ui->channelB5_Label);
    m_channelBList.append(ui->channelB6_Label);
    m_channelBList.append(ui->channelB7_Label);
    m_channelBList.append(ui->channelB8_Label);

    ui->stop_Btn->setVisible(false);
    ui->pause_Btn->setVisible(false);

    m_spasmTipsDialog = new SpasmTipsDialog();

    m_emergencyDialog = new EmergencyStopDialog();

    setTitle();

    connect(IceModule::getInstance(),SIGNAL(signalSetFesAParam(int*,int)),this,SLOT(slotSetChannelAData(int*,int)));
    connect(IceModule::getInstance(),SIGNAL(signalSetFesBParam(int*,int)),this,SLOT(slotSetChannelBData(int*,int)));
    connect(IceModule::getInstance(),SIGNAL(signalSetBicycleParam(ST_BicycleParam)),this,SLOT(slotSetBicycleParam(ST_BicycleParam)));

    connect(CCommunicateAPI::getInstance(),SIGNAL(signalReadyRead(QByteArray)),this,SLOT(slotReceiveData(QByteArray)));

    heartTimer = new QTimer();
    connect(heartTimer,SIGNAL(timeout()),this,SLOT(slotHeartTimer()));
    heartTimer->setInterval(1000);
    heartTimer->start();
#ifdef HEARTBEAT
    heartTimer->start();
#endif
    countDownTimer = new QTimer();
    countDownTimer->setInterval(1000);
    connect(countDownTimer,SIGNAL(timeout()),this,SLOT(slotCountDownTimer()));
    initGameSocket();

    m_reportDialog = new TrainReport();

    m_quitDialog = new QuitGameDialog();

    connect(ui->back1_Btn,SIGNAL(clicked()),this,SLOT(slotBackClicked()));
    connect(ui->back2_Btn,SIGNAL(clicked()),this,SLOT(slotBackClicked()));

    ui->warnTips_Label->setVisible(false);

    st_trainReport.passiveTime = 0;
    st_trainReport.activeTime = 0;

    ui->groupBox_6->setVisible(false);
}

GameDisplayPage::~GameDisplayPage()
{
    if(m_leftAnimation)
        delete m_leftAnimation;
    if(m_rightAnimation)
        delete m_rightAnimation;
    if(heartTimer)
        delete heartTimer;
    if(countDownTimer)
        delete countDownTimer;
    if(m_reportDialog)
        delete m_reportDialog;
    if(m_quitDialog)
        delete m_quitDialog;
    if(m_emergencyDialog)
        delete m_emergencyDialog;
    delete ui;
}

void GameDisplayPage::initGameSocket()
{
    m_gameSocket = new QUdpSocket();
    int16_t port = 2100;

    if(m_gameSocket->bind(QHostAddress("127.0.0.1"),port))
    {
        qDebug()<<(QString("游戏服务端口%1").arg(port));
    }
    connect(m_gameSocket,&QUdpSocket::readyRead,this,&GameDisplayPage::slotReceiveGameData);
}

void GameDisplayPage::setUser(const ST_PatientMsg &st_patientMsg)
{
    ui->user_Btn->setText(st_patientMsg.name);
}

void GameDisplayPage::setTitle()
{
    //设置title效果
    ui->user_Btn->setIcon(QIcon(":/DependFile/Source/User/user1.png"));
    ui->user_Btn->setIconSize(QSize(40,40));
}

void GameDisplayPage::setTrainPart(int type)
{
    m_bodyPart = type;
    switch(type)
    {
    case 0:
        ui->upLimp_GroupBox->move(20,135);
        ui->heart_GroupBox->move(20,320);
        ui->upLimp_GroupBox->setVisible(true);
        ui->downLimp_GroupBox->setVisible(false);
        ui->title_Label->setText(tr("上肢训练"));
        break;
    case 1:
        ui->downLimp_GroupBox->move(20,135);
        ui->heart_GroupBox->move(20,320);
        ui->upLimp_GroupBox->setVisible(false);
        ui->downLimp_GroupBox->setVisible(true);
        ui->title_Label->setText(tr("下肢训练"));
        break;
    case 2:
        ui->upLimp_GroupBox->move(20,135);
        ui->downLimp_GroupBox->move(20,320);
        ui->heart_GroupBox->move(20,505);
        ui->upLimp_GroupBox->setVisible(true);
        ui->downLimp_GroupBox->setVisible(true);
        ui->title_Label->setText(tr("四肢训练"));
        break;
    }
}

//实时数据填充
void GameDisplayPage::setSlaveParam(ST_DeviceParam &st_deviceParam)
{
    ST_GameControlParam st_gameControlParam;
    switch(m_bodyPart)
    {
    case 0: //上肢
    {
        if(st_deviceParam.upLimpSpeed > SpeedMax)
            st_deviceParam.upLimpSpeed = SpeedMax;
        ui->upRealSpeed_Label->setText(QString::number(st_deviceParam.upLimpSpeed));
        ui->upRealPower_Label->setText(QString::number(st_deviceParam.upPower));
        setActivePassiveSwitchMode(st_deviceParam.currentMode);
        //运动距离怎么计算
        ui->length_Label->setText(QString::number(st_deviceParam.upLimpCircle*0.628,'f',2) + "m");
        st_gameControlParam.speed = st_deviceParam.upLimpSpeed;

        st_gameControlParam.forceLeft = st_deviceParam.upBalance;
        st_gameControlParam.forceRight = 100 - st_deviceParam.upBalance;
    }
        break;
    case 1: //下肢
    {
        if(st_deviceParam.downLimpSpeed > SpeedMax)
            st_deviceParam.downLimpSpeed = SpeedMax;
        ui->downRealSpeed_Label->setText(QString::number(st_deviceParam.downLimpSpeed));
        ui->downRealPower_Label->setText(QString::number(st_deviceParam.downPower));
        setActivePassiveSwitchMode(st_deviceParam.currentMode);
        ui->length_Label->setText(QString::number(st_deviceParam.downLimpCircle*0.628,'f',2) + "m");
        st_gameControlParam.speed = st_deviceParam.downLimpSpeed;

        st_gameControlParam.forceLeft = st_deviceParam.downBalance;
        st_gameControlParam.forceRight = 100 - st_deviceParam.downBalance;
    }
        break;
    case 2: //上下肢
    {
        if(st_deviceParam.upLimpSpeed > SpeedMax)
            st_deviceParam.upLimpSpeed = SpeedMax;
        ui->upRealSpeed_Label->setText(QString::number(st_deviceParam.upLimpSpeed));
        ui->upRealPower_Label->setText(QString::number(st_deviceParam.upPower));
        if(st_deviceParam.downLimpSpeed > SpeedMax)
            st_deviceParam.downLimpSpeed = SpeedMax;
        ui->downRealSpeed_Label->setText(QString::number(st_deviceParam.downLimpSpeed));
        ui->downRealPower_Label->setText(QString::number(st_deviceParam.downPower));
        setActivePassiveSwitchMode(st_deviceParam.currentMode);
        ui->length_Label->setText(QString::number(st_deviceParam.upLimpCircle*0.628,'f',2) + "m");

        if(st_deviceParam.upLimpSpeed >= st_deviceParam.downLimpSpeed)
        {
            st_gameControlParam.forceLeft = st_deviceParam.upBalance;
            st_gameControlParam.forceRight = 100 - st_deviceParam.upBalance;
        }
        else
        {
            st_gameControlParam.forceLeft = st_deviceParam.downBalance;
            st_gameControlParam.forceRight = 100 - st_deviceParam.downBalance;
        }

        st_gameControlParam.speed = st_deviceParam.upLimpSpeed > st_deviceParam.downLimpSpeed?st_deviceParam.upLimpSpeed:st_deviceParam.downLimpSpeed;
    }
        break;
    }

    st_trainReport.upLimpLength = st_deviceParam.upLimpCircle*0.628;
    st_trainReport.downLimpLength = st_deviceParam.downLimpCircle*0.628;

    //此处显示的是左右平衡,但是下位机上传的是上下肢平衡
    ui->leftBalance_Label->setText(QString::number(st_gameControlParam.forceLeft) +"%");
    ui->rightBalance_Label->setText(QString::number(st_gameControlParam.forceRight)+"%");

    static int skipNum = 0;
    ++skipNum;
    if(skipNum > 20)
    {
        QPair<int,int> balancePair;
        balancePair.first = st_deviceParam.upBalance;
        balancePair.second = st_deviceParam.downBalance;
        //左右平衡计数
        balanceList.append(balancePair);
    }

    //触发急停(必须放在痉挛前,原因暂时未找到)
#if 1
    if( 1 == st_deviceParam.emergencyState)
    {
        IceModule::getInstance()->setEmergencyState(true);
        if(m_emergencyDialog->isVisible())
            return;
        //训练界面未开始训练
        if(m_st_bicycleParam.controlState == 0 )
        {
            if(this->isVisible())
            {
                //退出游戏
                sendStopCmd();
                //显示急停弹框
                m_emergencyDialog->show();
                //切到主界面,关闭当前页显示,关闭游戏container
                //                emit signalGameStateChanged(0);
            }
            else
            {
                m_emergencyDialog->show();
            }
        }
        //训练界面已开始训练
        else
        {
            if(m_spasmTipsDialog->isVisible())
            {
                m_spasmTipsDialog->stopPlayBell();
                m_spasmTipsDialog->close();
            }
            //退出游戏
            sendStopCmd();
            //显示急停弹框
            m_emergencyDialog->show();
            //关闭倒计时
            countDownTimer->stop();
            //切换界面
            //            emit signalGameStateChanged(0);
            st_trainReport.passiveTime = 0;
            st_trainReport.activeTime = 0;
            //切换为未训练状态
            m_st_bicycleParam.controlState = 0;
        }
    }
    else
    {
        IceModule::getInstance()->setEmergencyState(false);
        if(m_emergencyDialog->isVisible())
        {
            m_emergencyDialog->close();
        }
        //非急停状态下发送数据驱动游戏
        st_gameControlParam.speed *= 0.3;
        if(st_gameControlParam.speed < 1.1 && st_gameControlParam.speed > 0)
            st_gameControlParam.speed = 1.1;
        sendGameControlParam(st_gameControlParam);
    }
#endif

    if(1 == st_deviceParam.spasmState )
    {
        if(m_spasmTipsDialog->isVisible())
            return;
        m_spasmTimes++;
        //痉挛次数用于报告
        st_trainReport.spasmTimes = m_spasmTimes;

        switch(m_currentDirection)
        {
        case 0: //逆向
            m_spasmTipsDialog->setSpasmCompletedDirection(1);
            break;
        case 1: //正向
            m_spasmTipsDialog->setSpasmCompletedDirection(0);
            break;
        }

        m_spasmTipsDialog->setSpasmDialogVisible(true,m_spasmTimes);

        if(m_currentDirection)
            m_currentDirection = 0;
        else
            m_currentDirection = 1;

        if(1 == m_currentDirection)
        {
            ui->forward_Btn->setChecked(true);
            ui->backward_Btn->setChecked(false);
        }
        //逆向
        else if(0 == m_currentDirection)
        {
            ui->forward_Btn->setChecked(false);
            ui->backward_Btn->setChecked(true);
        }

        if(m_spasmTimes >= 3)
        {
            m_spasmTimes = 0;
            //大于3次痉挛退出训练
            on_stop_Btn_clicked();
        }
    }
}

void GameDisplayPage::open_Btn_clicked()
{
    m_leftAnimation->setStartValue(QPoint(-430,120));
    m_leftAnimation->setEndValue(QPoint(0,120));
    m_rightAnimation->setStartValue(QPoint(1920,120));
    m_rightAnimation->setEndValue(QPoint(1490,120));
    m_leftAnimation->start(QAbstractAnimation::KeepWhenStopped);
    m_rightAnimation->start(QAbstractAnimation::KeepWhenStopped);
}

void GameDisplayPage::close_Btn_clicked()
{
    m_leftAnimation->setStartValue(QPoint(0,120));
    m_leftAnimation->setEndValue(QPoint(-430,120));
    m_rightAnimation->setStartValue(QPoint(1490,120));
    m_rightAnimation->setEndValue(QPoint(1920,120));
    m_leftAnimation->start(QAbstractAnimation::KeepWhenStopped);
    m_rightAnimation->start(QAbstractAnimation::KeepWhenStopped);
}

void GameDisplayPage::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_UNUSED(event)

    if(event->pos().x() > 434 && event->pos().x() < 1482)
    {
        if(m_openState)
            close_Btn_clicked();
        else
            open_Btn_clicked();
        m_openState = !m_openState;
    }
}

void GameDisplayPage::on_upSpeedMinus_Btn_clicked()
{
    int speed = ui->upSpeed_Label->text().toInt();
    if(speed > 2)
    {
        --speed;
        ui->upSpeed_Label->setText(QString::number(speed));
        setTrainSpeed(speed);
        m_st_bicycleParam.speed = speed;
    }
}

void GameDisplayPage::on_upSpeedPlus_Btn_clicked()
{
    int speed = ui->upSpeed_Label->text().toInt();

    if(speed < 60)
    {
        ++speed;
        ui->upSpeed_Label->setText(QString::number(speed));
        setTrainSpeed(speed);
        m_st_bicycleParam.speed = speed;
    }
}

void GameDisplayPage::on_upForceMinus_Btn_clicked()
{
    int force = ui->upForce_Label->text().toInt();
    if(force > 1)
    {
        --force;
        ui->upForce_Label->setText(QString::number(force));
        setTrainFore(force);
        m_st_bicycleParam.resistance = force;
    }
}

void GameDisplayPage::on_upForcePlus_Btn_clicked()
{
    int force = ui->upForce_Label->text().toInt();
    if(force < 20)
    {
        ++force;
        ui->upForce_Label->setText(QString::number(force));
        setTrainFore(force);
        m_st_bicycleParam.resistance = force;
    }
}


void GameDisplayPage::slotSetChannelAData(int *data,int size)
{
    if(size <= 8 )
        for(int i = 0;i <size;i++)
            m_channelAList.at(i)->setText(QString::number(data[i]));

}

void GameDisplayPage::slotSetChannelBData(int *data,int size)
{
    if(size <= 8 )
        for(int i = 0;i <size;i++)
            m_channelBList.at(i)->setText(QString::number(data[i]));

}

/*******踏车设置参数,根据参数设置界面来填充数据*******/
void GameDisplayPage::slotSetBicycleParam(ST_BicycleParam st_setBicycleParam)
{
    m_st_bicycleParam = st_setBicycleParam;
    m_startNum = m_st_bicycleParam.trainTime * 60;

    m_spasmTipsDialog->setSpasmCompletedDirection(st_setBicycleParam.spasmType);
    //训练模式
    setTrainMode(m_st_bicycleParam.trainMode);
    //主被动模式按钮状态切换
    switchButtonState(m_st_bicycleParam.trainMode);
    //设置训练部位
    setTrainPart(st_setBicycleParam.bodyPart);
    //上肢
    if(0 == st_setBicycleParam.bodyPart || 2 == st_setBicycleParam.bodyPart)
    {
        //主动训练速度设置成0
        if(1 == m_st_bicycleParam.trainMode)
            st_setBicycleParam.speed = 0;
        ui->upSpeed_Label->setText(QString::number(st_setBicycleParam.speed));

        ui->upForce_Label->setText(QString::number(st_setBicycleParam.resistance));
        ui->upRemainTime_Label->setText(QString::number(m_st_bicycleParam.trainTime));

        //正向
        if(1 == st_setBicycleParam.direction)
        {
            ui->forward_Btn->setChecked(true);
            ui->backward_Btn->setChecked(false);
        }
        //逆向
        else if(0 == st_setBicycleParam.direction)
        {
            ui->forward_Btn->setChecked(false);
            ui->backward_Btn->setChecked(true);
        }
    }
    //下肢
    if(1 == st_setBicycleParam.bodyPart || 2 == st_setBicycleParam.bodyPart)
    {
        //主动训练速度设置成0
        if(1 == m_st_bicycleParam.trainMode)
            st_setBicycleParam.speed = 0;
        ui->upSpeed_Label->setText(QString::number(st_setBicycleParam.speed));
        ui->upForce_Label->setText(QString::number(st_setBicycleParam.resistance));
        ui->downRemainTime_Label->setText(QString::number(m_st_bicycleParam.trainTime));
        //正向
        if(1 == st_setBicycleParam.direction)
        {
            ui->forward_Btn->setChecked(true);
            ui->backward_Btn->setChecked(false);
        }
        //逆向
        else if(0 == st_setBicycleParam.direction)
        {
            ui->forward_Btn->setChecked(false);
            ui->backward_Btn->setChecked(true);
        }
    }

    //获取当前方向
    m_currentDirection = st_setBicycleParam.direction;

    st_patientMsg = CurrentUserData::getInstace()->getCurrentPatientMsg();

    //填充报告内容
    //患者基础信息
    st_trainReport.ID = st_patientMsg.ID;
    st_trainReport.name = st_patientMsg.name;
    st_trainReport.sex = st_patientMsg.sex;
    st_trainReport.phone = st_patientMsg.phone;
    st_trainReport.age = st_patientMsg.age;
    st_trainReport.markMsg = st_patientMsg.markMsg;
    //训练设置参数
    st_trainReport.trainMode = m_st_bicycleParam.trainMode;
    st_trainReport.bodyIndex = m_st_bicycleParam.bodyPart;
    st_trainReport.trainTime = m_st_bicycleParam.trainTime;

    //初始化平衡值
    st_trainReport.leftBalance = 0;
    st_trainReport.rightBalance = 0;

}

//接收下位机数据
void GameDisplayPage::slotReceiveData(QByteArray array)
{
    switch(array[2])
    {
    case BRFORE_START_CMD:  //启动前

    case AFTER_START_CMD:  //启动后
    {
        ST_DeviceParam  st_deviceParam;
        memcpy(&st_deviceParam,array.data() + 3,sizeof(ST_DeviceParam));
        setSlaveParam(st_deviceParam);
    }
        break;
    case RECE_HEARTBEAT_CMD:
        ++heartCount;
        break;
    }
}

void GameDisplayPage::slotHeartTimer()
{
    CCommunicateAPI::getInstance()->sendHeartBeat();
    static int num = 0;
    ++num;
    if(num > 3)
    {
        num = 0;
        QPixmap pixmap;
        if(heartCount < 1)
        {
            IceModule::getInstance()->setBicycleDeviceState(false);
            pixmap.load(":/DependFile/Source/signal/deviceDisconnected.png");
        }
        else
        {
            IceModule::getInstance()->setBicycleDeviceState(true);
            pixmap.load(":/DependFile/Source/signal/deviceConnected.png");
        }
        if(heartCount >= 3)
        {
            heartCount = 0;
        }
        ui->wifiSignal_Label->setPixmap(pixmap);
    }
}

void GameDisplayPage::slotCountDownTimer()
{
    --m_startNum;

    if(m_startNum < 0)
    {
        countDownTimer->stop();
        return;
    }

    int minNum = m_startNum/60;//分钟数
    int secNum = m_startNum%60;//秒数

    //训练时间计时
    ++st_trainReport.trainTime;

    //计算主被动时间
    switch(m_currentMode)
    {
    case 0: //被动
        ++st_trainReport.passiveTime;
        break;
    case 1://主动
        ++st_trainReport.activeTime;
        break;
    case 9://单独主动
        st_trainReport.passiveTime+=1;
        break;
    case 10://被动可切主动
        st_trainReport.activeTime += 1;
        break;
    case 11:
    case 12:
        ++st_trainReport.passiveTime;
        ++st_trainReport.activeTime;
        break;
    }

    //填入阻力值
    resistentList<<ui->upForce_Label->text().toInt();

    if(minNum == 0 && secNum == 0)
    {
        m_startNum = 0;
        //关闭定时器
        countDownTimer->stop();

        ui->upRemainTime_Label->setText("0");
        ui->downRemainTime_Label->setText("0");
        //告知下位机停止训练
        m_st_bicycleParam.controlState = 0;
        CCommunicateAPI::getInstance()->sendBicycleParam(m_st_bicycleParam);
        //弹出报告
        //计算结果数据(平衡度、距离等)
        calculateResultData();
        //弹出训练报告
        m_reportDialog->setReportData(st_trainReport,1);

        //开窗
        if(!m_openState)
        {
            open_Btn_clicked();
            m_openState = !m_openState;
        }

        st_trainReport.passiveTime = 0;
        st_trainReport.activeTime = 0;
        st_trainReport.trainTime = 0;

        sendStopCmd();
    }
    else
    {
        ui->upRemainTime_Label->setText(QString::number(minNum+1));
        ui->downRemainTime_Label->setText(QString::number(minNum+1));
    }
}

void GameDisplayPage::slotStopTraining()
{
    m_st_bicycleParam.controlState = 0;
    CCommunicateAPI::getInstance()->sendBicycleParam(m_st_bicycleParam);
}

void GameDisplayPage::slotReceiveGameData()
{
    while(m_gameSocket->hasPendingDatagrams())
    {
        QByteArray buf;
        buf.resize(m_gameSocket->pendingDatagramSize());
        m_gameSocket->readDatagram(buf.data(),buf.size());
        parseGameMsg(buf);
    }
}

void GameDisplayPage::slotBackClicked()
{
    //首先停止运动
    m_st_bicycleParam.controlState = 0;
    CCommunicateAPI::getInstance()->sendBicycleParam(m_st_bicycleParam);
    m_quitDialog->exec();
    if(m_quitDialog->getResult() == 1)
    {
        //开窗
        if(!m_openState)
        {
            open_Btn_clicked();
            m_openState = !m_openState;
        }
        quitTrain();
        //        emit signalGameStateChanged(0);
    }
    else
    {
        if(E_gameState == PAUSE || E_gameState == STOP)
            return;
        m_st_bicycleParam.controlState = 1;
        CCommunicateAPI::getInstance()->sendBicycleParam(m_st_bicycleParam);
    }
}

void GameDisplayPage::quitTrain()
{
    //关闭定时器
    countDownTimer->stop();
    //退出游戏
    sendStopCmd();
}

void GameDisplayPage::changeModeTips(QString str)
{
    ui->warnTips_Label->setVisible(true);
    ui->warnTips_Label->setText(str);
    //显示3s后隐藏
//    QTimer::singleShot(3000,this,[this](){
//        ui->warnTips_Label->setVisible(false);
//    });
}

void GameDisplayPage::switchButtonState(int8_t mode)
{
    switch(mode)
    {
    case 0://被动不设置阻力
        //上肢速度
        setSpeedState(true);
        //上肢阻力
        setForceState(false);
        break;
    case 1://主动
        //上肢速度
        setSpeedState(false);
        //上肢阻力
        setForceState(true);
        break;
    default:
        setSpeedState(true);
        setForceState(true);
        break;
    }
}

//解析游戏数据
void GameDisplayPage::parseGameMsg(QByteArray jsonArray)
{
    qDebug()<<jsonArray;
    QJsonParseError jsonError;
    QJsonDocument doucment = QJsonDocument::fromJson(jsonArray, &jsonError);  // 转化为 JSON 文档

    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError))
    {
        if(doucment.isObject())
        {
            QJsonObject object = doucment.object();  // 转化为对象
            if(object.contains("MsgID"))
            {
                QString str = object.value("MsgID").toString();
                int msgID = str.toInt();

                switch(msgID)
                {
                case 3: //开始游戏
                    emit signalGameStateChanged(1);
                    break;
                case 4: //退出游戏
                {
                    QTimer::singleShot(200,this,[this](){
                        emit signalGameStateChanged(0);
                    });
                }
                    break;
                }
            }
        }
    }
    else
        qDebug()<<"jsonError.error"<<jsonError.error;

}

void GameDisplayPage::sendGameControlParam(ST_GameControlParam st_gameControlParam)
{
    st_gameControlParam.MsgId = 1;
    QJsonObject object;
    object.insert("MsgID",st_gameControlParam.MsgId);
    object.insert("userName",st_gameControlParam.userName);
    object.insert("ID",st_gameControlParam.ID);
    object.insert("speed",st_gameControlParam.speed);
    object.insert("forceLeft",st_gameControlParam.forceLeft*0.7);
    object.insert("forceRight",st_gameControlParam.forceRight*0.7);
    object.insert("steps",30);
    object.insert("calories",5);

    //左右平衡度数据

    QJsonDocument document;
    document.setObject(object);
    QByteArray sendArray = document.toJson(QJsonDocument::Compact);

    QString ip("127.0.0.1");
    int16_t port = 12000;
    m_gameSocket->writeDatagram(sendArray,QHostAddress(ip),port);
}

void GameDisplayPage::sendStopCmd()
{
    QJsonObject object;
    object.insert("MsgID",2);
    object.insert("GameState",0);
    QJsonDocument document;
    document.setObject(object);
    QByteArray sendArray = document.toJson(QJsonDocument::Compact);
    QString ip("127.0.0.1");
    int16_t port = 12000;

    m_gameSocket->writeDatagram(sendArray,QHostAddress(ip),port);
}

void GameDisplayPage::sendStopCmdThreeTimes()
{
    sendStopCmd();
    QTimer::singleShot(400,this,[this](){
        sendStopCmd();
    });
}

void GameDisplayPage::calculateResultData()
{
    //计算平衡度
    int upBalance = 0,downBalance = 0;
    int upSum = 0,downSum = 0;
    for(int i = 0;i < balanceList.size();i++)
    {
        upSum += balanceList.at(i).first;
        downSum += balanceList.at(i).second;
    }
    upBalance = ((float)upSum)/balanceList.size();
    downBalance = ((float)downSum)/balanceList.size();

    //报告中的平衡度
    switch(m_bodyPart)
    {
    case 0: //上肢
        st_trainReport.leftBalance = upBalance;
        st_trainReport.rightBalance = 100 - upBalance;
        break;
    case 1: //下肢
        st_trainReport.leftBalance = downBalance;
        st_trainReport.rightBalance = 100 - downBalance;
        break;
    case 2: //上下肢
        st_trainReport.leftBalance = upBalance;
        st_trainReport.rightBalance = 100 - upBalance;
        break;
    }

    //计算阻力值
    int maxResistent = 0,minResistent = 200,sumResistent = 0,aveResistent = 0;
    if(!resistentList.empty())
    {
        for(int i = 0;i < resistentList.size();i++)
        {
            if(maxResistent < resistentList.at(i))
                maxResistent = resistentList.at(i);
            if(minResistent > resistentList.at(i))
                minResistent = resistentList.at(i);
            sumResistent += resistentList.at(i);
        }
        if(resistentList.size() > 0)
            aveResistent = sumResistent/resistentList.size();
    }

    st_trainReport.minResistance = minResistent;
    st_trainReport.maxResistance = maxResistent;
    st_trainReport.averangeResistance = aveResistent;

}

void GameDisplayPage::initButton()
{
    ui->stop_Btn->setVisible(false);
    ui->pause_Btn->setVisible(false);
    ui->start_Btn->setVisible(true);
    ui->length_Label->setText("0.00m");
    ui->leftBalance_Label->setText("50%");
    ui->rightBalance_Label->setText("50%");
}

void GameDisplayPage::setTrainSpeed(int speed, qint8 type)
{
    if(0 == type)
        CCommunicateAPI::getInstance()->sendRealTimeParam(PASSIVE_SPEED,speed);
    else if(1 == type)
        CCommunicateAPI::getInstance()->sendRealTimeParam(EQUAL_SPEED,speed);
}

void GameDisplayPage::setTrainFore(int force, qint8 type)
{
    Q_UNUSED(type)
    CCommunicateAPI::getInstance()->sendRealTimeParam(RESISTANCE_CMD,force);
}

void GameDisplayPage::setTrainDirection(qint8 direction, qint8 type)
{
    //direction 默认为1
    Q_UNUSED(type)
    CCommunicateAPI::getInstance()->sendRealTimeParam(SWITCH_DIRECTION,direction);
}

void GameDisplayPage::switchFes(qint8 channel, bool ok)
{
    Q_UNUSED(channel)
    Q_UNUSED(ok)
}

void GameDisplayPage::on_start_Btn_clicked()
{
    if(0 == gameState)
    {
        //训练起始时间
        st_trainReport.startTimeStr = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        st_trainReport.trainTime = 0;
        st_trainReport.activeTime = 0;
        st_trainReport.passiveTime = 0;
    }
    GameControl::getInstance()->playTipMusic("./DependFile/Music/startTraining.mp3");
    //已开始
    gameState = 1;

    E_gameState = START;

    ui->start_Btn->setVisible(false);
    ui->stop_Btn->setVisible(true);
    ui->pause_Btn->setVisible(true);

    //告知下位机开始运动
    if(m_st_bicycleParam.controlState == 2)
        m_st_bicycleParam.controlState = 3;
    else
        m_st_bicycleParam.controlState = 1;

    CCommunicateAPI::getInstance()->sendBicycleParam(m_st_bicycleParam);
    //开始时间计时器
    countDownTimer->start();
}

void GameDisplayPage::on_stop_Btn_clicked()
{
    E_gameState = STOP;

    ui->start_Btn->setVisible(false);
    ui->stop_Btn->setVisible(false);
    ui->pause_Btn->setVisible(false);
    GameControl::getInstance()->playTipMusic("./DependFile/Music/stopTraining.mp3");
    //告知下位机停止训练
    m_st_bicycleParam.controlState = 0;
    CCommunicateAPI::getInstance()->sendBicycleParam(m_st_bicycleParam);
    //关闭定时器
    countDownTimer->stop();

    sendStopCmd();
    //停止游戏运动
    ST_GameControlParam st_gameControlParam;
    st_gameControlParam.speed = 0;
    st_gameControlParam.forceLeft = 50;
    st_gameControlParam.forceRight = 50;
    sendGameControlParam(st_gameControlParam);

    //计算结果数据(平衡度、距离等)
    calculateResultData();
    //弹出训练报告
    m_reportDialog->setReportData(st_trainReport,1);
    //开窗
    if(!m_openState)
    {
        open_Btn_clicked();
        m_openState = !m_openState;
    }

    st_trainReport.activeTime = 0;
    st_trainReport.passiveTime = 0;
    //退出游戏
    //    sendStopCmd();
    //    Sleep(SleepTime);

    //    emit signalGameStateChanged(0);
}

void GameDisplayPage::on_pause_Btn_clicked()
{
    E_gameState = PAUSE;

    GameControl::getInstance()->playTipMusic("./DependFile/Music/pauseTraining.mp3");
    //关闭定时器
    countDownTimer->stop();
    m_st_bicycleParam.controlState = 2;
    CCommunicateAPI::getInstance()->sendBicycleParam(m_st_bicycleParam);
    ui->start_Btn->setVisible(true);
    ui->stop_Btn->setVisible(false);
    ui->pause_Btn->setVisible(false);

    ui->upRealPower_Label->setText("0");
    ui->upRealSpeed_Label->setText("0");

    ui->downRealPower_Label->setText("0");
    ui->downRealSpeed_Label->setText("0");

    if(m_st_bicycleParam.trainMode == 7 || m_st_bicycleParam.trainMode == 10)
    {
        ui->upCurrentStage_Label->setText(tr("主动模式"));
        //将当前模式切成主动
        m_currentMode = 1;
    }
}

void GameDisplayPage::on_switchAFes_Btn_clicked()
{
    QMessageBox::warning(NULL,tr("提示"),tr("未检测到电刺激设备"));
    return;
    if(ui->switchAFes_Btn->styleSheet() == "border-image: url(:/DependFile/Source/gamePage/switchOn.png);")
    {
        ui->switchAFes_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/switchOff.png);");
    }
    else if(ui->switchAFes_Btn->styleSheet() == "border-image: url(:/DependFile/Source/gamePage/switchOff.png);")
    {
        ui->switchAFes_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/switchOn.png);");
    }
}

void GameDisplayPage::setTrainMode(int8_t mode)
{
    QString modeName;
    switch(mode)
    {
    case 0:
        modeName = tr("被动");
        break;
    case 1:
        modeName = tr("主动");
        break;
    case 2:
        modeName = tr("助力");
        break;
    case 3:
        modeName = tr("等速");
        break;
    case 4:
        modeName = tr("协同被动");
        break;
    case 5:
        modeName = tr("上肢带下肢");
        break;
    case 6:
        modeName = tr("下肢带上肢");
        break;
    case 7:
        modeName = tr("主被动");
        break;
    case 8:
        modeName = tr("FES");
        break;
    case 9:
        modeName = tr("主动");
        break;
    case 10:
        modeName = tr("主被动");
        break;
    case 11:
        ui->upCurrentStage_Label->setText(tr("主动"));
        break;
    case 12:
        ui->upCurrentStage_Label->setText(tr("被动"));
        break;
    }
    ui->upCurrentStage_Label->setText(modeName);
}

void GameDisplayPage::setActivePassiveSwitchMode(int8_t mode)
{
    if(m_currentMode == mode)
        return;
    if(m_currentMode != mode)
    {
        QString modeName;
        switch(mode)
        {
        case 0:
            modeName = tr("被动");
            break;
        case 1:
            modeName = tr("主动");
            break;
        case 2:
            modeName = tr("助力");
            break;
        case 3:
            modeName = tr("等速");
            break;
        case 4:
            modeName = tr("协同被动");
            break;
        case 5:
            modeName = tr("上肢带下肢");
            break;
        case 6:
            modeName = tr("下肢带上肢");
            break;
        case 7:
            modeName = tr("主被动");
            break;
        case 8:
            modeName = tr("FES");
            break;
        case 9:
            modeName = tr("主动");
            break;
        case 10:
            modeName = tr("主被动");
            break;
        case 11:
            //            ui->upCurrentStage_Label->setText(tr("主动"));
            break;
        case 12:
            //            ui->upCurrentStage_Label->setText(tr("被动"));
            break;
        }
        //        ui->upCurrentStage_Label->setText(modeName);
        if(m_st_bicycleParam.trainMode == 7 || m_st_bicycleParam.trainMode == 10)
        {
            changeModeTips(modeName);
        }
        m_currentMode = mode;
    }
}


//填充设置参数
void GameDisplayPage::fillSetParam(int updown,int speed,int resistance,int direction)
{
    //上肢
    upDirection = direction;
    if(upDirection == 1)
        on_forward_Btn_clicked();
    else if(upDirection == 0)
        on_backward_Btn_clicked();
    ui->upSpeed_Label->setText(QString::number(speed));
    ui->upForce_Label->setText(QString::number(resistance));

}

void GameDisplayPage:: setPulseOxygen(const ST_PulseOxygen& pulseOxygen)
{
    //    ui->pulse_Label->setText(QString::number(pulseOxygen.pulse));
    //    ui->oxygen_Label->setText(QString::number(pulseOxygen.oxygen));
}

void GameDisplayPage::setCenterParam(int left, int right, int length)
{
    ui->leftBalance_Label->setText(QString::number(left) + "%");
    ui->leftBalance_Label->setText(QString::number(right) + "%");
    ui->leftBalance_Label->setText(QString::number(length) + "m");
}

void GameDisplayPage::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)
    QPainter painter(this);
    painter.fillRect(rect(),QColor(0,0,0,10));
}

void GameDisplayPage::showEvent(QShowEvent *event)
{
    Q_UNUSED(event)
    initButton();
    gameState = 0;//未开始
    m_spasmTimes = 0;
    st_trainReport.spasmTimes = 0;

    ui->upRealPower_Label->setText("0");
    ui->upRealSpeed_Label->setText("0");

    ui->downRealPower_Label->setText("0");
    ui->downRealSpeed_Label->setText("0");

    balanceList.clear();
    resistentList.clear();

}


void GameDisplayPage::on_forward_Btn_clicked()
{
    setTrainDirection(1);
    m_st_bicycleParam.direction = 1;
}

void GameDisplayPage::on_backward_Btn_clicked()
{
    setTrainDirection(0);
    m_st_bicycleParam.direction = 0;
}


void GameDisplayPage::on_switchFes_Btn_clicked()
{
    QString fesA("border-image: url(:/DependFile/Source/gamePage/checkA.png);");
    QString fesB("border-image: url(:/DependFile/Source/gamePage/checkB.png);");
    if(ui->switchFes_Btn->styleSheet() == fesA)
    {
        ui->switchFes_Btn->setStyleSheet(fesB);
    }
    else if(ui->switchFes_Btn->styleSheet() == fesB)
    {
        ui->switchFes_Btn->setStyleSheet(fesA);
    }
}

void GameDisplayPage::changeEvent(QEvent* event)
{
    switch (event->type())
    {
    case QEvent::LanguageChange:
    {
        E_LANGUAGE language = LanguageManager::getInstance()->getCurrentLanguage();
        switch(language)
        {
        case Chinese_E:
            ui->stop_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/stop.png);");
            ui->pause_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/pause.png);");
            break;
        case English_E:
            ui->stop_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/stop_E.png);");
            ui->pause_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/pause_E.png);");
            break;
        }
        ui->retranslateUi(this);
    }
        break;
    default:
        QWidget::changeEvent(event);
        break;
    }
}

//设置速度使能状态
void GameDisplayPage::setSpeedState(bool enabled)
{
    ui->upSpeedMinus_Btn->setEnabled(enabled);
    ui->upSpeedPlus_Btn->setEnabled(enabled);
    ui->speed_GroupBox->setEnabled(enabled);

    if(enabled)
    {
        ui->upSpeedMinus_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/minus1.png);");
        ui->upSpeedPlus_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/plus1.png);");
        ui->speed_GroupBox->setStyleSheet("#speed_GroupBox{background: #FFFFFF;\nborder: 1px solid #05A6EC;}");
    }
    else
    {
        ui->upSpeedMinus_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/minusDis.png);");
        ui->upSpeedPlus_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/plusDis.png);");
        ui->speed_GroupBox->setStyleSheet("#speed_GroupBox{background: #ECECEC;\nborder: 1px solid #05A6EC;}");
    }
}

//设置阻力使能状态
void GameDisplayPage::setForceState(bool enabled)
{
    ui->upForceMinus_Btn->setEnabled(enabled);
    ui->upForcePlus_Btn->setEnabled(enabled);
    ui->force_GroupBox->setEnabled(enabled);

    if(enabled)
    {
        ui->upForceMinus_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/minus1.png);");
        ui->upForcePlus_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/plus1.png);");
        ui->force_GroupBox->setStyleSheet("#force_GroupBox{background: #FFFFFF;\nborder: 1px solid #05A6EC;}");
    }
    else
    {
        ui->upForceMinus_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/minusDis.png);");
        ui->upForcePlus_Btn->setStyleSheet("border-image: url(:/DependFile/Source/gamePage/plusDis.png);");
        ui->force_GroupBox->setStyleSheet("#force_GroupBox{background: #ECECEC;\nborder: 1px solid #05A6EC;}");
    }
}