#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,Qt::AutoConnection);
    connect(this,&SendSystem::sigSendXMLmessage,dataParser->ClientAnswer(),&ClientAnswerParser::message,Qt::AutoConnection);
    connect(this,&SendSystem::sigSendNotify,dataParser->ClientAnswer(),&ClientAnswerParser::notify,Qt::DirectConnection); //потому что возвращает значение
    connect(this,&SendSystem::sigSendVersion,dataParser->ClientAnswer(),&ClientAnswerParser::currentVersion,Qt::AutoConnection);

    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();

    QFile file(path);
    QFileInfo fileInfo(file);

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

        file.close();
        return;
    }

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


    fileSize = fileInfo.size();

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


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

    stream << path << fileSize;



    socket->waitForBytesWritten(10);

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

            if(socket->state() == QAbstractSocket::UnconnectedState) break;
            countSend++;
        }

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

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

void SendSystem::sendVersion()
{
    QByteArray data = dataParser->ClientAnswer()->currentVersion();
    sendXmlAnswer(data);
}

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(commandHashCompleteClient);
}

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::sendPacketType(PacketType packetType)
{
    QDataStream stream(socket);
    stream.setVersion(QDataStream::Qt_DefaultCompiledVersion);
    stream << packetType;
    socket->waitForReadyRead(100);
}

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

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

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

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


    socket->waitForReadyRead(1000);
}

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

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

    QListIterator<FileData> clientIterator(deleteList);

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

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

    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(isSendStopped) return;
    }

    emit sigLoadHash();

    sendPacketType(PacketType::TYPE_FINISH);
}

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

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

bool SendSystem::socketFlush()      //TODO: проверить использование
{
    return socket->flush();
}

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

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

SendSystem::~SendSystem()
{

}
