#include "Client.h"
#include "recognizesystem.h"

RecognizeSystem::RecognizeSystem(QObject *parent):
QObject(parent)
{
    packetType = PacketType::TYPE_NONE;
    filePath.clear();
    fileSize = 0;
    sizeReceiveData = 0;
    tmpBlock.clear();
    countSend = 0;
    mutex = new QMutex;

}

void RecognizeSystem::initialize(UpdateController *updateController,DataParser* dataParser,
    ServerLMSWidget *server,SendSystem *sendSystem, ClientHandler *handler)
{
    this->updateController = updateController;
    this->dataParser = dataParser;
    this->server = server;
    this->clientHandler = handler;
    this->sendSystem = sendSystem;
    socket = handler->getSocket();

    connect(this,&RecognizeSystem::sigCalculateHash,updateController,&UpdateController::calculateHash,Qt::DirectConnection);
    connect(this,&RecognizeSystem::sigXmlParser,dataParser,&DataParser::xmlParser,Qt::DirectConnection);
    qDebug() << "Recognize init thread ID " << QThread::currentThreadId();
}

void RecognizeSystem::recognize()
{
    mutex->lock();
    qDebug() << "Recognize thread ID " << QThread::currentThreadId();
    QDataStream stream(socket);
    stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);
    QByteArray data;
    Client *client = clientHandler->getClient();

    while (socket->bytesAvailable() > 0)
    {

        if (packetType == PacketType::TYPE_NONE)
        {
            stream.startTransaction();

            if(!isPackageTypeInited)        //первичная инициализация для типа клиента
            {
                char *read = new char[0];
                stream.readRawData(read,1);
                packetType = static_cast<PacketType>(QString(read[0]).toInt());

                packetTypeInit(packetType,client);

                if(!stream.commitTransaction()) continue;
                continue;
            }

            if(client->getIsUnity())
            {
                char *read = new char[0];
                stream.readRawData(read,1);
                packetType = static_cast<PacketType>(QString(read[0]).toInt());

                if(!stream.commitTransaction()) continue;
                continue;
            }
            else
            {
                stream >> packetType;

                if(!stream.commitTransaction()) continue;
            }

        }

        if (packetType == PacketType::TYPE_COMMAND)
        {
            stream.startTransaction();
            stream >> command;

            if (!stream.commitTransaction()) continue;
        }

        if (command == "update")        //запускает процесс оновления
        {
            sendSystem->updateFiles(updateController->getFileSendList(),
                                    updateController->getClientDataList());

            qDebug()<< "Call update";
            packetType = PacketType::TYPE_NONE;
            command = "";
        }

        if (packetType == PacketType::TYPE_XMLANSWER)
        {

            if(clientHandler->getClient()->getIsUnity())
            {
                data = socket->readAll();
            }
            else
            {
                stream.startTransaction();
                stream >> data;

                if(!stream.commitTransaction()) continue;
            }

            qDebug() << data;
            emit sigXmlParser(clientHandler,data);
            //dataParser->xmlParser(clientHandler,data);
            packetType = PacketType::TYPE_NONE;
            continue;
        }

        if(packetType == PacketType::TYPE_FOLDER)   //создание папок

        {
            if(client->getIsUnity())
            {
                filePath = socket->readAll();
                filePath = Tools::createRootScenario(filePath);
            }
            else
            {
                stream.startTransaction();
                stream >> filePath;

                if(!stream.commitTransaction()){
                    continue;
                }

                filePath = createFullPath(filePath);

            }

            QDir dir(filePath);
            if(!dir.exists()){
                if(dir.mkpath(filePath)){
                    qDebug() << "Dir Created";
                }
            }

            packetType = PacketType::TYPE_NONE;
            continue;
        }

        if (packetType == PacketType::TYPE_FILE)  //выгрузка одного файла
        {

            if(client->getIsUnity())
            {
                DataInfo *currentFileData = dataParser->getCurrentDataInfo();
                filePath = currentFileData->path;

                filePath = Tools::createLocalPath(filePath);

                filePath = Tools::createUpdateFilePath(filePath);

                filePath = Tools::createRootScenario(filePath);

                QFile file(filePath);


                if (file.exists())
                {
                    file.remove();  //удаление файла, если он уже есть, но необходимо обновить
                    qDebug() << Tools::getTime() + "Delete exist file: " + filePath;
                }

                if (!file.open(QFile::Append))
                {
                    QString folderPath = Tools::createFolderPath(filePath);
                    qDebug() << "FULL PATH: " << folderPath;
                    QDir dir(folderPath);
                    if (!dir.exists()){
                        dir.mkpath(".");
                    }

                    file.open(QFile::Append);
                }

                //socket->waitForReadyRead(1000);

                fileSize = currentFileData->size;

                qint64 readSize = 65535;
                forever
                {
                    if(fileSize < readSize)
                    {
                        readSize = fileSize;
                        qDebug() << "LastPackage: " << readSize;
                    }

                    socket->waitForReadyRead(20);
                    tmpBlock = socket->read(readSize);

                    quint64 toFile = file.write(tmpBlock);
                    fileSize -= toFile;
                    sizeReceiveData += toFile;
                    countSend++;

                    tmpBlock.clear();
                    qDebug() << "Loading progress: " << fileSize << "/" << currentFileData->size;

                    if(fileSize == 0) break;

                }

                file.close();
                filePath.clear();
                dataParser->clearCurrentDataInfo();

                socket->waitForReadyRead(100);

                packetType = PacketType::TYPE_NONE;

            }
            else
            {
                forever
                {
                    stream.startTransaction();
                    stream >> filePath;
                    stream >> fileSize;

                    if(!stream.commitTransaction()) continue;

                    filePath = createFullPath(filePath);
                    socket->waitForReadyRead(100);
                    break;
                }

                QFile file(filePath);
                QFileInfo fileInfo(file);

                if(file.exists())
                {
                    file.remove();
                }

                file.open(QFile::Append);

                forever
                {
                    stream.startTransaction();
                    stream >> tmpBlock;

                    if(!stream.commitTransaction()){

                        if(socket->state() == QAbstractSocket::UnconnectedState){
                            qDebug() << "UNCONNECT";
                            mutex->unlock();
                            file.close();
                            return;
                        }
                        if(socket->waitForReadyRead(TCP_READ_TIMEOUT)){
                            continue;
                        }

                        continue;
                    }

                     quint64 toFile = file.write(tmpBlock);
                     sizeReceiveData += toFile;
                     countSend++;

                     tmpBlock.clear();

                     if(sizeReceiveData == fileSize) break;


                }

                QString logMessage = Tools::getTime() + " ";
                logMessage.append("Load from " + client->getLogin() + " ");
                logMessage.append(fileInfo.fileName());

                emit sigSendToLogger(logMessage);

                file.close();

                if(command == "check")
                {
                    QFile checkFile(filePath);
                    checkFile.open(QIODevice::ReadOnly);
                    updateController->compareFiles(clientHandler,checkFile.readAll());
                    checkFile.close();
                }

                filePath.clear();
                fileSize = 0;
                tmpBlock.clear();
                sizeReceiveData = 0;
                countSend = 0;

            }

        }

        if (packetType == PacketType::TYPE_FILESIZE)
        {
            fileSize = socket->readAll().toULong();
            qDebug() << fileSize;
            packetType = PacketType::TYPE_NONE;
            continue;
        }

        if (packetType == PacketType::TYPE_FINISH)
        {
            emit sigCalculateHash();
            packetType = PacketType::TYPE_NONE;
        }

        packetType = PacketType::TYPE_NONE;
    }

    mutex->unlock();
}

void RecognizeSystem::packetTypeInit(PacketType packet,Client *client)
{
    if(packet == PacketType::TYPE_QT)
    {
        client->setUnity(false);

        qDebug() << "ConnectionType isUnity: " << client->getIsUnity();
    }
    else if (packet == PacketType::TYPE_UNITY)
    {
        client->setUnity(true);
    }

     isPackageTypeInited = true;

    packetType = PacketType::TYPE_NONE;
}

QString RecognizeSystem::createFullPath(QString path)
{
    QString fullPath;
    qint8 pos = path.indexOf("Application");

    QString localPath = path.remove(0,--pos);

    //qDebug() << "CLIENT: localPath" << localPath;
    fullPath = QDir::currentPath() + localPath;

    return fullPath;
}

RecognizeSystem::~RecognizeSystem()
{

}
