#include "UpdateController.h"
#include <QDialogButtonBox>

UpdateController::UpdateController(DataParser *parser,SendSystem *sendSystem, QObject *parent) :
    QObject(parent)
{
    this->dataParser = parser;
    this->sendSystem = sendSystem;
    applicationFolderPath = QDir::currentPath() + applicationFolderName;
}

void UpdateController::initialize(MainWindow *mainWindow)
{
    connect(this,&UpdateController::sigUpdateComplete,mainWindow,&MainWindow::showCompleteDialogBox);
}

void UpdateController::calculateCommonHash()
{
    appDataList.clear();
    appDataList = calculateHash(applicationFolderPath,"StreamingAssets");
    calculateStreamingHash();
    appDataList.append(streamingDataList);
    dataParser->createFileDataList(appDataList,fullStaticDataFolderName + hashFilename);
    qDebug() << "UpdateController threadID " << QThread::currentThreadId();
}

void UpdateController::calculateStreamingHash()
{
    streamingDataList.clear();
    streamingDataList = calculateHash(QDir::currentPath() + streamingAssetsPath,"");
    std::sort(streamingDataList.begin(),streamingDataList.end());
    dataParser->createFileDataList(streamingDataList,streamingHashFilename);
}

void UpdateController::setServerVersion(StreamingVersionData *version)
{
    serverVersion = version;
}

QList<FileData> UpdateController::calculateHash(QString path,QString ignoreName)
{
    qDebug() << "Try calculate";

    QDir dir(path);
    QDirIterator iterator(dir,QDirIterator::Subdirectories);
    QList<FileData> *hashes = new QList<FileData>;

     if(!QDir(path).exists())
     {  //проверка на наличие папки
        QDir().mkdir(path);
    }

    QString hashString;

    while (iterator.hasNext())
    {
        iterator.next();
        QFileInfo fileInfo = iterator.fileInfo();
        FileData currentFile;
        QFile file(fileInfo.absoluteFilePath());

        quint64 fileSize = file.size();     //буффер для хэширования крупных файлов
        const quint64 bufferSize = 10240;

        if(fileInfo.isHidden()) continue;
        if(ignoreName != "" && fileInfo.path().contains(ignoreName)) continue;

        if(fileInfo.isFile() && file.open(QIODevice::ReadOnly))
        {
            char buffer[bufferSize];
            int bytesRead;
            int readSize = qMin(fileSize,bufferSize);

            QCryptographicHash hash(QCryptographicHash::Md5);

            while(readSize > 0 && (bytesRead = file.read(buffer,readSize)) > 0){
                fileSize -= bytesRead;
                hash.addData(buffer,bytesRead);
                readSize = qMin(fileSize,bufferSize);
            }

            hashString = QString(hash.result().toHex());
            currentFile.path = Tools::createLocalPath(fileInfo.absoluteFilePath());
            currentFile.hash = hashString;
            hashes->push_back(currentFile);
            file.close();
        }
        else if (fileInfo.isDir() && !fileInfo.isRoot() && fileInfo.fileName() != "..")
        {
            currentFile.path = Tools::createLocalPath(fileInfo.path());
            currentFile.hash = "FOLDER";

            if(!hashes->contains(currentFile))
            {
                hashes->push_back(currentFile);
            }
        }

    }

    std::sort(hashes->begin(),hashes->end());

    return *hashes;
}

void UpdateController::updateFilesOnServer(QList<FileData> *fileSendList){

    QListIterator<FileData> serverIterator(*fileSendList);
    try {

        while(serverIterator.hasNext())
        {
            FileData data = serverIterator.next();

            if (data.hash == "FOLDER")
            {
                sendSystem->sendFolderBlock(data.path);
            }
            else
            {
                sendSystem->sendFileBlock(data.path);
            }

        }

        calculateCommonHash();

        sendSystem->sendFinish();

        emit sigUpdateComplete(true);
    }
    catch (...)
    {
        emit sigUpdateComplete(false);
    }

}

StreamingVersionData *UpdateController::getServerVersion() const
{
    return serverVersion;
}


UpdateController::~UpdateController()
{

}
