#include "RsyncDryRunTask.h"
#include "global.h"
#include "Device.h"
#include <QDebug>
#include <QString>
#include <QStringList>
#include <QJsonObject>

RsyncDryRunTask::RsyncDryRunTask(bool reportProgress) : RsyncTask(reportProgress)
{}

RsyncDryRunTask::~RsyncDryRunTask()
{}

void RsyncDryRunTask::setDestUUID(const QString &destUUID)
{
    m_destUUID = destUUID;
}

bool RsyncDryRunTask::getPartitionSpace(quint64 &availableBytes)
{
    if (m_destUUID.isEmpty()) {
        qWarning()<<Q_FUNC_INFO<<" m_destUUID is empty!";
        return false;
    }

    DevicePtr pDevice(new Device(m_destUUID));
    if (!pDevice->getDeviceInfo().isNull()) {
        pDevice->calculateDiskSpace();
        availableBytes = pDevice->getDeviceInfo()->availableBytes;
        return true;
    }

    return false;
}

void RsyncDryRunTask::readStandardOutput()
{
    const QString totalTransferred = "Total transferred file size:";
    bool running = true;
    while (running && m_process->canReadLine()) {
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
        QStringList lines = QString(m_process->readLine()).split('\r', Qt::SkipEmptyParts);
#else
        QStringList lines = QString(m_process->readLine()).split('\r', QString::SkipEmptyParts);
#endif
        for (auto &line : lines) {
            if (line.contains(totalTransferred)) {
                // Total transferred file size: 47,936,868,682 bytes
                QString totalBytes = line.replace(",", "").trimmed();
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
                QStringList curList = totalBytes.split(" ", Qt::SkipEmptyParts);
#else
                QStringList curList = totalBytes.split(" ", QString::SkipEmptyParts);
#endif
                if (curList.size() >= 5) {
                    quint64 requiredBytes = curList.at(4).toULongLong();
                    this->reportSpace(requiredBytes);
                    running = false;
                    break;
                }
            }
        }
    }
}

void RsyncDryRunTask::reportSpace(const quint64 &spaceBytes)
{
    bool hasSpace = false;
    const quint64 reservedBytes = static_cast<quint64> (300 * MiB);
    quint64 requiredBytes = spaceBytes + reservedBytes;
    quint64 availableBytes = 0;
    if (this->getPartitionSpace(availableBytes)) {
        if (availableBytes >= requiredBytes) {
            hasSpace = true;
        }
    }

    QJsonObject jsonObject;
    jsonObject.insert("hasSpace", hasSpace);
    jsonObject.insert("requiredBytes", QString::number(requiredBytes));
    jsonObject.insert("availableBytes", QString::number(availableBytes));
    jsonObject.insert("totalSizeBytes", QString::number(spaceBytes));

    Q_EMIT spaceChanged(jsonObject);
}

void RsyncDryRunTask::doResult()
{
    // remove dry-run temp dir
    const QString localHost = "localhost";
    QString dryRunTempPath = m_dest.left(m_dest.length() - localHost.length());
    if (dryRunTempPath.contains(" ")) {
        dryRunTempPath = QString("\"%1\"").arg(dryRunTempPath);
    }

    QString out;
    QString err;
    QStringList args;
    args<<"-rf"<<dryRunTempPath;
    if (!Process::spawnCmd("rm", args, out,err)) {
        qWarning()<<Q_FUNC_INFO<<", spawnCmd failed, err = "<<err;
    }
}
