#include "sendsystem.h"


SendSystem::SendSystem(QObject *parent) : QObject(parent)
{
    isSendStopped = false; 
}

void SendSystem::initialize(DataParser *dataParser,Logger *logger)
{
    this->dataParser = dataParser;
    this->logger = logger;

    connect(this,&SendSystem::sigSendToLogger,logger,&Logger::addTextToLogger);
    connect(this,&SendSystem::sigSendXMLmessage,dataParser,&DataParser::xmlAnswer_message,Qt::BlockingQueuedConnection);
    connect(this,&SendSystem::sigSendNotify,dataParser,&DataParser::xmlAnswer_notify,Qt::BlockingQueuedConnection);

    qDebug() << "SendSystem thread: " << QThread::currentThreadId();
}

void SendSystem::setClient(Client *client,QTcpSocket *socket)
{
    this->socket = socket;
    this->isUnity = client->getIsUnity();
    this->client = client;
    isSendStopped = false;
}


void SendSystem::sendMessageBlock(QString message)
{
    auto messageBlock = emit sigSendXMLmessage(message);
    sendXmlAnswer(messageBlock);
}

void SendSystem::sendFileBlock(QString path)
{

     qDebug() << "sendFileBlock thread: " << QThread::currentThreadId();

    QDataStream stream(socket);
    stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);

    QFile file(Tools::createRootPath(path));
    QFileInfo fileInfo(file);
    fileSize = fileInfo.size();

    if(fileSize == 0){
        emit sigSendToLogger(Tools::getTime() +  " WARNING! Zero size " + path);
        return;
    }


    stream << PacketType::TYPE_FILE; //Отправляем тип блока

    stream << path << fileSize;

    if(isSendStopped) {             //Поведение на случай отключения клиента

        file.close();
        return;
    }


    socket->waitForBytesWritten();

    if(file.open(QFile::ReadOnly)){
        while(!file.atEnd()){
            QByteArray data = file.read(1025*250);
            stream << data;
            socket->waitForBytesWritten();
            countSend++;
        }

        emit sigSendToLogger(Tools::getTime() + " send file " + fileInfo.fileName());
    }

    file.close();
    countSend = 0;
    socket->waitForBytesWritten();
    socket->waitForReadyRead(100);
}

void SendSystem::socketWrite(QByteArray array)
{
    socket->write(array);
    socket->waitForBytesWritten(100);
}

void SendSystem::socketClose()
{
    socket->close();
}

void SendSystem::sendFileBlockWithRename(QString path, QString newName)
{
    qDebug() << "sendFileBlockWithRename thread: " << QThread::currentThreadId();

    QDataStream stream(socket);
    stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);

    QFile file(Tools::createRootPath(path));
    QFileInfo fileInfo(file);
    fileSize = fileInfo.size();

    if(fileSize == 0){
        emit sigSendToLogger(Tools::getTime() +  " WARNING! Zero size " + path);
        return;
    }

    QString pathForSend = Tools::createFolderPath(path) + "/" + staticDataFolderName + newName;

    stream << PacketType::TYPE_FILE; //Отправляем тип блока

    stream << pathForSend << fileSize;

    if(isSendStopped) {             //Поведение на случай отключения клиента

        file.close();
        return;
    }


    socket->waitForBytesWritten();

    if(file.open(QFile::ReadOnly)){
        while(!file.atEnd()){
            QByteArray data = file.read(1025*250);
            stream << data;
            socket->waitForBytesWritten();
            countSend++;
        }

        emit sigSendToLogger(Tools::getTime() + " send file " + fileInfo.fileName());
    }

    file.close();
    countSend = 0;
    socket->waitForBytesWritten();
    socket->waitForReadyRead(100);

    sendNotify("HASHSENDCOMPLETE");
}

void SendSystem::sendFolderBlock(QString path)
{
    QDataStream stream(socket);
    stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);

    stream << PacketType::TYPE_FOLDER;
    stream << path;
    socket->waitForReadyRead(100);
}

void SendSystem::sendDeleteBlock(QString path)
{
    QDataStream stream(socket);
    stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);

    stream << PacketType::TYPE_DELETE;
    stream << path;
    socket->waitForReadyRead(100);
}

void SendSystem::sendHello()
{
    socket->write(SERVER_HELLO);
}

void SendSystem::sendFinish()
{
    QDataStream stream(socket);
    stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);
    stream << PacketType::TYPE_FINISH;
    socket->waitForReadyRead(100);
}

void SendSystem::sendNotify(QString notify)
{
    qDebug() << "SendNotify thread: " << QThread::currentThreadId();
    auto answer = emit sigSendNotify(notify);//"END");
    sendXmlAnswer(answer);
}

void SendSystem::sendXmlAnswer(QByteArray array)
{
    qDebug() << "SendSystemThread: " << QThread::currentThreadId();
    if(!client->getIsUnity())
    {
        QDataStream stream(socket);
        stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);

        stream << PacketType::TYPE_XMLANSWER;
        stream << array;
    }
    else
    {
        socket->write(array);
    }


    socket->waitForReadyRead(1000);
}

void SendSystem::sendNeedUpdate(bool flag,quint64 size,quint64 fileCount)
{
    QDataStream stream(socket);
    stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);
    stream << PacketType::TYPE_NEEDUPDATE;
    stream << flag;
    stream << size;
    stream << fileCount;
}

void SendSystem::updateFiles(QList<FileData> fileSendList, QList<FileData> clientDataList){

    QListIterator<FileData> serverIterator(fileSendList);

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

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

        if(getIsSendStopped()) return;
    }

    QListIterator<FileData> clientIterator(clientDataList);

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

        sendDeleteBlock(data.path);
        if(getIsSendStopped()) return;
    }

    emit sigLoadHash();

    sendFinish();
}



void SendSystem::sendStop()
{
    isSendStopped = true;
}

bool SendSystem::getIsSendStopped() const
{
    return isSendStopped;
}

SendSystem::~SendSystem()
{

}
