#include "gamecontrol.h"
#include <QFile>
#include <QTextStream>
#include "readconfig.h"
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QDateTime>
#include "currentuserdata.h"
#include "cdatabaseinterface.h"
#include <QTimer>

//LOG4QT_DECLARE_STATIC_LOGGER(logger, GameControl)

GameControl* GameControl::m_GameParamControl = NULL;

GameControl::GameControl(QWidget *parent)
    : QWidget(parent),
      m_gameSocket(NULL),
//      m_waitingDialog(NULL),
      m_trainReport(NULL),
      waitTimer(NULL),
      m_activeMaxAngle(0),
      m_activeMinAngle(0),
      currentGameID(0)
{
    m_Process = new QProcess();
//    initGameSocket();
//    m_waitingDialog = new WaitingDialog();
//    m_waitingDialog->setWaitingType(INITWAITING);
    m_trainReport = new TrainReport();

    waitTimer = new QTimer();
    waitTimer->setInterval(500);
    waitTimer->setSingleShot(true);
    connect(waitTimer,SIGNAL(timeout()),this,SLOT(slotWaitTimer()));

    player = new QMediaPlayer();
}

GameControl::~GameControl()
{
    if(m_trainReport)
    {
        delete m_trainReport;
    }
    if(waitTimer)
    {
        delete waitTimer;
    }
    if(player)
    {
        delete player;
    }
}

void GameControl::initGameSocket()
{
    m_gameSocket = new QUdpSocket();
    int16_t port;
    QString IP;
    ReadConfig::getInstance()->getGameServerAddress(port,IP);
    if(m_gameSocket->bind(port))
    {
        qDebug()<<(QString("游戏服务端口%1").arg(port));
    }
    connect(m_gameSocket,&QUdpSocket::readyRead,this,&GameControl::slotReceiveGameData);
}

GameControl* GameControl::getInstance()
{
    if(!m_GameParamControl)
    {
        m_GameParamControl = new GameControl();
    }
    return m_GameParamControl;
}

void GameControl::updateXml(ST_GameParam& st_GameParam)
{
    QFile file("./gameExecutable/gameConfig.xml");
    if(!file.open(QFile::ReadOnly))
        return;
    QDomDocument doc;

    if(!doc.setContent(&file))
    {
        file.close();
        return;
    }
    file.close();

    QDomElement root = doc.documentElement();

    if(1)
    {
        QDomNodeList timeList = root.elementsByTagName("GameTime");
        QDomNode timeNode = timeList.at(0);
        QDomNode oldnode=timeNode.firstChild();
        timeNode.firstChild().setNodeValue(QString::number(st_GameParam.gameTime));
        QDomNode newNode = timeNode.firstChild();
        timeNode.replaceChild(newNode,oldnode);
    }
    if(1)
    {
        QDomNodeList levelList = root.elementsByTagName("Level");
        QDomNode levelNode = levelList.at(0);
        QDomNode oldLevelnode=levelNode.firstChild();
        levelNode.firstChild().setNodeValue(QString::number(st_GameParam.hardLevel));
        QDomNode newLevelNode = levelNode.firstChild();
        levelNode.replaceChild(newLevelNode,oldLevelnode);
    }
    if(1)
    {
        QDomNodeList List = root.elementsByTagName("Speed");
        QDomNode node = List.at(0);
        QDomNode oldLevelnode=node.firstChild();
        node.firstChild().setNodeValue(QString::number(st_GameParam.speed));
        QDomNode newLevelNode = node.firstChild();
        node.replaceChild(newLevelNode,oldLevelnode);
    }
    if(1)
    {
        QDomNodeList List = root.elementsByTagName("TrainType");
        QDomNode node = List.at(0);
        QDomNode oldLevelnode=node.firstChild();
        node.firstChild().setNodeValue(QString::number(st_GameParam.trainType));
        QDomNode newLevelNode = node.firstChild();
        node.replaceChild(newLevelNode,oldLevelnode);
    }
    if(1)
    {
        QDomNodeList List = root.elementsByTagName("AngleVlue");
        QDomNode node = List.at(0);
        QDomNode oldLevelnode=node.firstChild();
        node.firstChild().setNodeValue(QString::number(st_GameParam.angleValue));
        QDomNode newLevelNode = node.firstChild();
        node.replaceChild(newLevelNode,oldLevelnode);
    }
    if(1)
    {
        QDomNodeList List = root.elementsByTagName("WaitTime");
        QDomNode node = List.at(0);
        QDomNode oldLevelnode=node.firstChild();
        node.firstChild().setNodeValue(QString::number(st_GameParam.waitTime));
        QDomNode newLevelNode = node.firstChild();
        node.replaceChild(newLevelNode,oldLevelnode);
    }
    if(1)
    {
        QDomNodeList List = root.elementsByTagName("MaxCircle");
        QDomNode node = List.at(0);
        QDomNode oldLevelnode=node.firstChild();
        node.firstChild().setNodeValue(QString::number(st_GameParam.maxCircle));
        QDomNode newLevelNode = node.firstChild();
        node.replaceChild(newLevelNode,oldLevelnode);
    }
    if(1)
    {
        QDomNodeList List = root.elementsByTagName("ReadPosTable");
        QDomNode node = List.at(0);
        QDomNode oldLevelnode=node.firstChild();
        QString ok("false");
        if(st_GameParam.readPosTable)
            ok = "true";
        else
            ok = "false";
        node.firstChild().setNodeValue(ok);
        QDomNode newLevelNode = node.firstChild();
        node.replaceChild(newLevelNode,oldLevelnode);
    }

    QDomNode n = root.firstChild();
    while(!n.isNull())
    {
        QDomElement e = n.toElement();
        if(!e.isNull())
        {
            if(e.tagName() == "TrainingTrack")
            {
                e.setAttribute("path",st_GameParam.trainTrackFilePath);
            }
        }
        n = n.nextSibling();
    }

    if(!file.open(QFile::WriteOnly|QFile::Truncate))
        return;
    //输出到文件
    QTextStream out_stream(&file);
    doc.save(out_stream,4); //缩进4格
    file.close();
}

void GameControl::setGamParam(ST_GameParam& st_GameParam)
{
    //将本地参数转化成游戏中用到的参数
    if(5 == st_GameParam.trainType)
        st_GameParam.trainType = 1;
    if(6 == st_GameParam.trainType)
        st_GameParam.trainType = 2;
    updateXml(st_GameParam);
}

void GameControl::readGameConfigMsg()
{
    QList<ST_GameMsg> gameMsgList;
    QFile file("./DependFile/ConfigFile/gameListConfig.xml");

    if(!file.open(QIODevice::ReadOnly))
    {
        qDebug()<<"read gameListConfig failed";
        return ;
    }
    QDomDocument doc;
    QString error;
    int row,colum;
    if(!doc.setContent(&file,&error,&row,&colum))
    {
        qDebug()<<"gameList error"<<error<<row<<colum;
        file.close();
        return ;
    }
    file.close();

    QDomElement root=doc.documentElement(); //返回根节点

    QDomNode node=root.firstChild(); //获得第一个子节点

    while(!node.isNull())
    {
        if(node.isElement()) //如果节点是元素
        {
            ST_GameMsg st_GameMsg;
            QDomElement e=node.toElement();
            st_GameMsg.gameID = e.attribute("ID").toInt();
            st_GameMsg.gameName = e.attribute("gameName");
            st_GameMsg.gamePath = e.attribute("path");
            st_GameMsg.iconPath = e.attribute("iconPath");
            st_GameMsg.className = e.attribute("className");
            st_GameMsg.windownName = e.attribute("windownName");
            gameMsgList.append(st_GameMsg);
            m_mapGameName.insert(st_GameMsg.gameID,st_GameMsg);
        }
        node = node.nextSibling();
    }

    m_gameMsgList = gameMsgList;
}

QList<ST_GameMsg> GameControl::getGameMsgs()
{
    return m_gameMsgList;
}

ST_GameMsg GameControl::getGameMsgByName(int ID)
{
    ST_GameMsg st_gameMsg;
    QMapIterator<int, ST_GameMsg> i(m_mapGameName);

    while(i.hasNext())
    {
        i.next();
    }

    if(m_mapGameName.contains(ID))
    {
        st_gameMsg = m_mapGameName.value(ID);
    }
    return st_gameMsg;
}

ST_GameMsg GameControl::getCurrentGameMsg()
{
    return getGameMsgByName(currentGameID);
}

void GameControl::startGame(QString path)
{
    //1.开启游戏进程
    if(path.isEmpty())
        return;
    QString hardDisk = path.mid(0,2);
    hardDisk.append("\n\r");

    QString gameName = path.mid(path.lastIndexOf('/')+1);
    gameName.prepend("start ");
    gameName.append("\n\r");
    QString gamePath = path.mid(0,path.lastIndexOf('/'));
    gamePath.prepend("cd ");
    gamePath.append("\n\r");
    m_Process->start("cmd.exe");
    //切换盘符
    m_Process->write(hardDisk.toLatin1());
    //进入文件夹
    m_Process->write(gamePath.toLatin1());
    //开启进程
    m_Process->write(gameName.toLatin1());
    m_Process->write("exit\n\r");
    m_Process->waitForFinished();
    m_Process->close();
    //2.关闭设备复位中的界面
}

//游戏数据接收
void GameControl::slotReceiveGameData()
{
    while(m_gameSocket->hasPendingDatagrams())
    {
        QByteArray buf;
        buf.resize(m_gameSocket->pendingDatagramSize());
        m_gameSocket->readDatagram(buf.data(),buf.size());
//        parseGameMsg(buf);
    }
}

/***
void GameControl::parseGameMsg(QByteArray jsonArray)
{
    QJsonParseError jsonError;
    QJsonDocument doucment = QJsonDocument::fromJson(jsonArray, &jsonError);  // 转化为 JSON 文档
 #if 1
    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError))
    {
        if(doucment.isObject())
        {
            QJsonObject object = doucment.object();  // 转化为对象
            if(object.contains("msgID"))
            {
                int msgID = object.value("msgID").toInt();
                switch(msgID)
                {
                case 1: //游戏开始信号
                {
                    m_spasmTimes = 0;
                    isTraining = true;
                    waitTimer->start();
                    st_TrainReport.startTime = QDateTime::currentDateTime();
                    emit signalGameState(e_TrainMode,GameStart_E);
                }
                    break;
                case 2: //游戏给出的目标位置
                {
                    {
                        if(object.contains("m_xv"))
                        {
                            QJsonObject xObject = object.value("m_xv").toObject();
                            int current = 0;
                            int max = 1;
                            if(xObject.contains("current"))
                                current = xObject.value("current").toInt();
                            if(xObject.contains("max"))
                                max = xObject.value("max").toInt();
                        }
                        if(object.contains("m_yv"))
                        {
                            QJsonObject yObject = object.value("m_yv").toObject();
                            int current = 0;
                            int max = 1;
                            if(yObject.contains("current"))
                                current = yObject.value("current").toInt();
                            if(yObject.contains("max"))
                                max = yObject.value("max").toInt();
                        }
                        if(object.contains("tarAngle"))
                        {
                            float angle = 0;
                            angle = object.value("tarAngle").toDouble();
//                            emit signalSendDestPosition(angle);
                        }
                    }

                }
                    break;
                case 3: //结束信息
                {
                    isTraining = false;
                    if(object.contains("quitType"))
                    {
                        //告知下位机训练完成
                        sendStopCmd();
                        m_quitType = object.value("quitType").toInt();
                        //正常退出
                        if(1 == m_quitType)
                        {
                            emit signalGameState(e_TrainMode,GameEnd_E);
                            st_TrainReport.endTime = QDateTime::currentDateTime();
                            if(object.contains("totalTime"))
                                st_TrainReport.duration = object.value("totalTime").toInt();
                            if(object.contains("totalScore"))
                                st_TrainReport.score = object.value("totalScore").toInt();
                        }
                        else
                        {
                            emit signalGameState(e_TrainMode,GameEnd_E);
                            st_TrainReport.endTime = QDateTime::currentDateTime();
                            if(object.contains("totalTime"))
                                st_TrainReport.duration = object.value("totalTime").toInt();
                            if(object.contains("totalScore"))
                                st_TrainReport.score = object.value("totalScore").toInt();
                        }
                        //生成训练报告
                        createTrainReport();
                    }
                }
                    break;
                }
            }
        }
    }
    else
    {

//        logger()->debug(jsonError.errorString());
        //此处不该在此处停止心跳
    }
#endif
}

***/
void GameControl::createTrainReport()
{
    /***
    ST_PatientMsg st_currentPatient = CurrentUserData::getInstace()->getCurrentPatientMsg();
    st_TrainReport.ID = st_currentPatient.ID;
    st_TrainReport.name = st_currentPatient.name;

    //从数据库中查询总时间
    int lastTotalDuration;
    QString query("select * from  TrainReport order by startTime DESC;");
    if(!CDatabaseInterface::getInstance()->exec(query))
        qDebug()<<CDatabaseInterface::getInstance()->getLastError()<<"ERROR";
    int count = CDatabaseInterface::getInstance()->getValuesSize();
    if(count >0)
    {
       QList<QVariantMap> maplist = CDatabaseInterface::getInstance()->getValues(0,1);
       ST_TrainReport st_trainReport = variantMapToTrainReport(maplist.at(0));
       lastTotalDuration = st_trainReport.totalDuration;
       st_TrainReport.totalDuration = lastTotalDuration + st_TrainReport.duration;
    }
    st_TrainReport.level = 1;
    if(0 == st_TrainReport.trainMode)
        m_trainReport->setReportType(tr("被动训练报告"));
    else if(1 == st_TrainReport.trainMode)
        m_trainReport->setReportType(tr("主动训练报告"));
    ***/
    m_trainReport->setReportData(st_TrainReport,1);
}

void GameControl::sendStopCmd()
{
    QJsonObject object;
    object.insert("msgID",2);
    object.insert("GameState",0);
    QJsonDocument document;
    document.setObject(object);
    QByteArray sendArray = document.toJson();
    QString ip("127.0.0.1");
    int16_t port = 12000;
    for(int i = 0;i < 5;i++)
    {
        m_gameSocket->writeDatagram(sendArray,QHostAddress(ip),port);
        Sleep(100);
    }
}

void GameControl::setTrainParam(ST_TrainParam &st_TrainParam)
{
    m_st_TrainParam = st_TrainParam;
}

ST_TrainParam GameControl::getTrainParam()
{
    return m_st_TrainParam;
}

//游戏界面关闭时间
void GameControl::slotWaitTimer()
{
    //关闭等待界面
//    m_waitingDialog->setDialogCloseState(true);
}

//关闭游戏
void GameControl::stopGame()
{
    sendStopCmd();
}

void GameControl::sendGameControlData(const ST_GameControlParam &st_gameControlParam)
{
    QJsonObject object;
    object.insert("msgID",st_gameControlParam.MsgId);
    object.insert("ID",st_gameControlParam.ID);
    object.insert("userName",st_gameControlParam.userName);
    object.insert("speed",st_gameControlParam.speed);
    object.insert("forceLeft",st_gameControlParam.forceLeft);
    object.insert("forceRight",st_gameControlParam.forceRight);
    object.insert("angle",st_gameControlParam.angle);

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

void GameControl::setCurrentGame(int ID)
{
    currentGameID = ID;
}

void GameControl::playTipMusic(QString path)
{
    player->setMedia(QUrl::fromLocalFile(path));
    player->setVolume(90);
    player->play();
}

int GameControl::getCurrentGameID()
{
    return currentGameID;
}