#include "OSTreeTask.h"
#include <QJsonObject>
#include <QDateTime>
#include <QDebug>
// journalctl -f /usr/sbin/deepin-upgrade-manager

static const int SUBMISSION_VERSION_PROGRESS = 5;
static const int COPY_REPO_DATA_PROGRESS = 10;
static const int SUBMITTED_VERSION_TO_REPO_PROGRESS = 15;
static const int NO_NEED_AUTO_CLEANUP_PROGRESS = 70;
static const int UPDATE_GRUB_PROGRESS = 80;
static const int ENDING_COMMIT_VERSION_PROGRESS = 94;

OSTreeTask::OSTreeTask() : AsyncTask()
{}

OSTreeTask::~OSTreeTask()
{
    this->stopTimer();
}

void OSTreeTask::init()
{
    m_cmd = "journalctl";
    m_progress = 0;
    m_remainSecond = 0;

    connect(&m_timer, &QTimer::timeout, this, &OSTreeTask::onTimeOut);
}

void OSTreeTask::onTimeOut()
{
    if (m_progress < SUBMISSION_VERSION_PROGRESS) {
        if (m_progress < SUBMISSION_VERSION_PROGRESS - 1) {
            static int countSubVer = 0;
            m_progress += (++countSubVer) / 2;
            if (countSubVer >= 2) {
                countSubVer = 0;
            }
        }

        if (m_progress < 1) {
            return;
        }
    //    qInfo() <<"onTimeOut m_progress "<<m_progress<<", m_remainSecond = "<<m_remainSecond<<", SUBMISSION_VERSION_PROGRESS = "<<SUBMISSION_VERSION_PROGRESS;
    } else if (m_progress < COPY_REPO_DATA_PROGRESS) {
        if (m_progress < COPY_REPO_DATA_PROGRESS - 1) {
            static int countCopyRepoData = 0;
            m_progress += (++countCopyRepoData) / 3;
            if (countCopyRepoData >= 3) {
                countCopyRepoData = 0;
            }
        }
    //    qInfo() <<"onTimeOut m_progress "<<m_progress<<", m_remainSecond = "<<m_remainSecond<<", COPY_REPO_DATA_PROGRESS = "<<COPY_REPO_DATA_PROGRESS;
    } else if (m_progress < SUBMITTED_VERSION_TO_REPO_PROGRESS) {
        if (m_progress < SUBMITTED_VERSION_TO_REPO_PROGRESS - 1) {
            static int countVerToRepo = 0;
            m_progress += (++countVerToRepo) / 2;
            if (countVerToRepo >= 2) {
                countVerToRepo = 0;
            }
        }
    //    qInfo() <<"onTimeOut m_progress "<<m_progress<<", m_remainSecond = "<<m_remainSecond<<", SUBMITTED_VERSION_TO_REPO_PROGRESS = "<<SUBMITTED_VERSION_TO_REPO_PROGRESS;
    } else if (m_progress < NO_NEED_AUTO_CLEANUP_PROGRESS) {
        if (m_progress < NO_NEED_AUTO_CLEANUP_PROGRESS - 1) {
            static int countNoAutoCleanup = 0;
            m_progress += (++countNoAutoCleanup) / 2;
            if (countNoAutoCleanup >= 2) {
                countNoAutoCleanup = 0;
            }
        }
    //    qInfo() <<"onTimeOut m_progress "<<m_progress<<", m_remainSecond = "<<m_remainSecond<<", NO_NEED_AUTO_CLEANUP_PROGRESS = "<<NO_NEED_AUTO_CLEANUP_PROGRESS;
    } else if (m_progress < UPDATE_GRUB_PROGRESS) {
        if (m_progress < UPDATE_GRUB_PROGRESS - 1) {
            static int countUpdateGrub = 0;
            m_progress += (++countUpdateGrub) / 2;
            if (countUpdateGrub >= 2) {
                countUpdateGrub = 0;
            }
        }
    //    qInfo() <<"onTimeOut m_progress "<<m_progress<<", m_remainSecond = "<<m_remainSecond<<", UPDATE_GRUB_PROGRESS = "<<UPDATE_GRUB_PROGRESS;
    } else if (m_progress < ENDING_COMMIT_VERSION_PROGRESS) {
        static int countEndCommitVer = 0;
        m_progress += (++countEndCommitVer) / 4;
        if (countEndCommitVer >= 4) {
            countEndCommitVer = 0;
        }
    //    qInfo() <<"onTimeOut m_progress "<<m_progress<<", m_remainSecond = "<<m_remainSecond<<", ENDING_COMMIT_VERSION_PROGRESS = "<<ENDING_COMMIT_VERSION_PROGRESS;
    } else {
        static int countFinish = 0;
        m_progress += (++countFinish) / 5;
        if (countFinish >= 5) {
            countFinish = 0;
        }
        if (m_progress >= 99) {
            m_progress = 99; // 这个阶段只用于更新剩余时间, 进度100%需要通过原子更新的信号来控制
        }
    //    qInfo() <<"onTimeOut m_progress "<<m_progress<<", m_remainSecond = "<<m_remainSecond<<", countFinish = "<<countFinish;
    }

    this->estimateRemainTime();
    reportProgress(m_progress, m_remainSecond);
}

void OSTreeTask::estimateRemainTime()
{
    QTime currTime = QTime::currentTime();
    int elapsed = m_startTime.msecsTo(currTime);
    double speed = (m_progress * 1000.0) / elapsed;
    if (0 < speed) {
        m_remainSecond = (100 - m_progress) / speed;
    }
}

void OSTreeTask::readStandardOutput()
{
    while (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) {
        //    qInfo()<<", line = "<<line;
            // 监控原子更新系统日志，按照顺序分阶段上报阶段性进度，在定时器里也是分阶段估算进度
            if (m_progress < SUBMISSION_VERSION_PROGRESS &&
                line.contains("the version number of this submission is:")) {
                m_progress = SUBMISSION_VERSION_PROGRESS;
                m_isBegin = true;
                reportProgress(m_progress, m_remainSecond);
        //        qInfo()<<"readStandardOutput, SUBMISSION_VERSION_PROGRESS, m_progress = "<<m_progress;
                continue;
            }

            if (!m_isBegin) {
                continue;
            }

            if (m_progress < COPY_REPO_DATA_PROGRESS && line.contains("[copyRepoData]")) {
                m_progress = COPY_REPO_DATA_PROGRESS;
                reportProgress(m_progress, m_remainSecond);
        //        qInfo()<<"readStandardOutput, COPY_REPO_DATA_PROGRESS, m_progress = "<<m_progress;
                continue;
            }

            if (m_progress < SUBMITTED_VERSION_TO_REPO_PROGRESS && line.contains("submitted version to the repo, version:")) {
                m_progress = SUBMITTED_VERSION_TO_REPO_PROGRESS;
                reportProgress(m_progress, m_remainSecond);
        //        qInfo()<<"readStandardOutput, SUBMITTED_VERSION_TO_REPO_PROGRESS, m_progress = "<<m_progress;
                continue;
            }

            if (m_progress < NO_NEED_AUTO_CLEANUP_PROGRESS &&
                (line.contains("no need for auto cleanup") || line.contains("need for cleanup repo"))) {
                m_progress = NO_NEED_AUTO_CLEANUP_PROGRESS;
                reportProgress(m_progress, m_remainSecond);
        //        qInfo()<<"readStandardOutput, NO_NEED_AUTO_CLEANUP_PROGRESS, m_progress = "<<m_progress;
                continue;
            }

            if (m_progress < UPDATE_GRUB_PROGRESS && line.contains("start update grub")) {
                m_progress = UPDATE_GRUB_PROGRESS;
                reportProgress(m_progress, m_remainSecond);
        //        qInfo()<<"readStandardOutput, UPDATE_GRUB_PROGRESS, m_progress = "<<m_progress;
                continue;
            }

            if (m_progress < ENDING_COMMIT_VERSION_PROGRESS && line.contains("ending commit a new version")) {
                m_progress = ENDING_COMMIT_VERSION_PROGRESS;
                reportProgress(m_progress, m_remainSecond);
        //        qInfo()<<"readStandardOutput, ENDING_COMMIT_VERSION_PROGRESS, m_progress = "<<m_progress;
                continue;
            }
        }
    }
}

void OSTreeTask::readAllStandardError()
{
    AsyncTask::readAllStandardError();
}

bool OSTreeTask::buildArgumentsForBackup()
{
    m_args.clear();
    m_args <<"--lines"<<"30"<<"-f"<<"/usr/sbin/deepin-upgrade-manager";

    return true;
}

bool OSTreeTask::buildArgumentsForRestore(const QString &)
{
    return true;
}

void OSTreeTask::doResult()
{}

void OSTreeTask::startTimer()
{
    m_timer.setInterval(1000);
    if (!m_timer.isActive()) {
        m_timer.start();
    }

    m_startTime = QTime::currentTime();
    m_progress = 0;
    m_remainSecond = 0;
    m_isBegin = false;
}

void OSTreeTask::stopTimer()
{
    if (m_timer.isActive()) {
        m_timer.stop();
    }
}

void OSTreeTask::reportProgress(int progress, int remainSecond)
{
    QJsonObject jsonObject;
    jsonObject.insert("progress", progress);
    jsonObject.insert("remainSecond", remainSecond);
    Q_EMIT progressChanged(jsonObject);
}
