#include "processearse.h"
#include "src/frame/logger.h"
#include "src/po/translation.h"
#include "src/data/datacdrom.h"
#include "src/view/modaldialog.h"
#include "src/frame/auditlog.h"
#include "src/frame/signals.h"
#include "src/process/processgetiso.h"
#include "src/process/processlsof.h"

#include <QFileInfo>
#include <QDebug>

ProcessEarse::ProcessEarse(void *cdrom, QObject *parent) :
    ProcessBasic(parent),
    m_oCDROM(cdrom),
    m_eraseValue(0),
    m_oPro(new QTimer(this))
{
    auditburner = new QGSettings("org.ukui.kylinburner");
    auditlogpath = "/var/log/kylin-burner/os_audit.log";
    m_isSpecialMachine = auditburner->get("burneraudit-isrunning").toBool();
    m_oCloneCDROM = ((DataCDROM *)cdrom)->clone();
    m_oDeviceBlock = m_oCloneCDROM->device();
    m_iValue = 0;

    LOGGER->registerName(this, _("PROCESS_EARSE"));
    MODAL->show();
    title(_("Earsing"));
    m_oProcessName = _("Earse");
    emit setRange(0, 100);
    emit setValue(0);

    connect(m_oPro, SIGNAL(timeout()), this, SLOT(slotsProgress()));
    connect(g_user_signal, &GlobalUserSignal::removeDisc, this, &ProcessEarse::slotsRemoveDisc);
    m_oPro->setInterval(1000);
    g_user_signal->setDeviceBusyStatus(m_oDeviceBlock,true);
}

bool ProcessEarse::prepare()
{
    QFileInfo fileInfo;

    PROGRESS;
    MODAL->show();
    connect(this, SIGNAL(cancel(bool)), MODAL, SLOT(cancelEnable(bool)));

    if (m_oCloneCDROM->mediumType().contains("CD")) {
        // CD盘 + aigo光驱，使用xorriso进行擦除
        if (m_oCloneCDROM->display().contains("aigo")) {
            LOGGER->info("CD盘， 光驱：aigo，使用xorriso命令刻录");
            fileInfo.setFile("/bin/xorriso");
        }else{
            fileInfo.setFile("/bin/cdrecord");
        }
    }else{
        fileInfo.setFile("/bin/xorriso");
    }

    if (!fileInfo.exists() || !fileInfo.isExecutable())
    {
        LOGGER->error(_("There is no %1 program or %1 cannot execute."
                "Please check the mkisofs is exists or not, and give "
                "the right permissions.%2 exiting...")
              .arg(fileInfo.absoluteFilePath())
              .arg("KylinBurner"));
        return false;
    }
    m_oProcess->setProgram(fileInfo.fileName());
    return true;
}

bool ProcessEarse::config()
{
    if (m_oCloneCDROM->isOpen()) {
        LOGGER->info(QString("(ProcessEarse::config)  disc(%1) close(%1)").arg(m_oCloneCDROM->device()));
        m_oCloneCDROM->close();
    }

    //非空盘需卸载
    if (m_oCloneCDROM->mediumStatus() != DataMedium::MEDIUM_EMPTY) {
        m_umountError = DataCDROM::umountMedium(m_oCloneCDROM->device());
        if (!m_umountError) {
            ProcessLsof lsofPro;
            if (lsofPro.checkDevice(m_oCloneCDROM)) {
                const QList<ProcessLsof::Process>& apps = lsofPro.usingApplications();
                if (apps.count() > 0) {
                    m_umountErrorStr = _("Device '%1' is used by the '%2' application! Please try again later").arg(m_oCloneCDROM->display()).arg(lsofPro.joinProcessNames(apps));
                }
            }

            LOGGER->info(QString("(ProcessBurnData::working) cdrom run umount: ").arg(m_umountErrorStr));
            return false;
        }
    }

    if (m_oCloneCDROM->mediumType().contains("CD"))
    {
        if (m_oCloneCDROM->display().contains("aigo")) {
            // CD盘 + aigo光驱，拼写xorriso命令参数
            m_oArguments << "-dev"
                         << QString("%1").arg(m_oCloneCDROM->device())
                         << "-blank"
                         << "fast"
                         << "-eject";
        } else {
            // CD盘, 拼写cdrecord命令参数
            m_oArguments << "blank=fast"
                         << "driveropts=burnfree"
                         << QString("dev=%1").arg(m_oCloneCDROM->device())
                         << "-v"
                         << "-eject";
        }
        setValue(m_iValue++, m_oIcon, _("Umount CD, and prepare to blank CD."));
    }
    else
    {
        LOGGER->info("( ProcessEarse::config ) umount finished");
        m_oArguments << "-dev" << m_oCloneCDROM->device() << "-format" << "full";
    }

    return m_oKeep;
}

bool ProcessEarse::worked()
{
    m_oCloneCDROM->eject();
    return m_oKeep;
}

void ProcessEarse::slotsOutput()
{
    QString output;

    output = m_oProcess->readAllStandardOutput();
    qDebug() << __func__ << __LINE__  << "output : " << output;
    LOGGER->info(QString("[%1] [%2] output: %3").arg(__func__).arg(__LINE__).arg(output));
    if (output.contains("Input/output error")) {
        m_oKeep = false;
    } else if(output.contains("Errno:")) {
        m_oKeep = false;
    }

    if (output.contains("Performing OPC"))
    {
        cancel(false);
        setValue(m_iValue++, m_oIcon, _("Performing OPC"));
        return;
    } else if (output.contains("Fixating")) {
        setValue(99, m_oIcon, _("Fixating(Will wait minutes)"));
        return;
    }

    if (!m_oPro->isActive()) {
        m_oPro->start();
    }
}

void ProcessEarse::slotsError()
{
    QString eraseCmdOutput;
    eraseCmdOutput = m_oProcess->readAllStandardError();
    qDebug() << __func__ << __LINE__  << "error : " << eraseCmdOutput;
    LOGGER->info(eraseCmdOutput);
    if(eraseCmdOutput.contains("Beginning to format medium")){
        m_eraseValue = 1;
        cancel(false);
    }else if(eraseCmdOutput.contains("Formatting done")){
        m_eraseValue = 99;
    }else if(eraseCmdOutput.contains("Device or resource busy")){
        LOGGER->error("Device or resource busy");
        m_umountError = false;
        m_oKeep = false;
        return;
    } else if(eraseCmdOutput.contains("xorriso : aborting")) {
        m_oKeep = false;
        return;
    } else if(eraseCmdOutput.contains("Formatting")){
        if(m_oCloneCDROM->mediumType().contains("DVD-RW")){
            int currentValue = -1;
            currentValue = (int)eraseCmdOutput.split(' ').at(7).mid(0,3).toDouble();
            if((currentValue - m_eraseValue) < 2)
                m_eraseValue = currentValue;
        }else{
            if(m_eraseValue + 5 >= 99)
                m_eraseValue = 99;
            else
                m_eraseValue += 5;
        }
    }

    emit setValue(m_eraseValue, m_oIcon, _("earsing...."));
}

void ProcessEarse::slotsFinished(int code, QProcess::ExitStatus status)
{
    if (m_oPro->isActive()){
        m_oPro->stop();
    }

    LOGGER->info(QString("Exit code is %1, status : %2, m_umountError = %3").arg(code).arg(status).arg(m_umountError));
    emit setValue(99, m_oIcon, _("earsing...."));

    if (QProcess::NormalExit == status && 0==code)
    {
        emit setValue(99, m_oIcon, _("Burn Data"));
        LOGGER->info( QString("slotsFinished() line[%1] : earse Medium success.").arg(__LINE__) );
        m_oCloneCDROM->eject();
    }
    else
    {
        m_oKeep = false;

        ProcessLsof lsofPro;
        if (lsofPro.checkDevice(m_oCloneCDROM)) {
            const QList<ProcessLsof::Process>& apps = lsofPro.usingApplications();
            if (apps.count() > 0) {
                m_umountErrorStr = _("Device '%1' is used by the '%2' application! Please try again later").arg(m_oCloneCDROM->display()).arg(lsofPro.joinProcessNames(apps));
                return;
            }
        }

        LOGGER->error( QString("slotsFinished() line[%1] : earse Medium failure. %2").arg(__LINE__).arg(m_oProcess->errorString()) );
    }

    if(m_isSpecialMachine==true){
        auditburner->set("burner-os-auditlog-name",auditlogpath);
        eraseLog.outputResult(m_oCloneCDROM->display(), m_oCloneCDROM->mediumType(), m_oProcessName, true==m_oKeep);
    } else {
        auditburner->set("burner-os-auditlog-name","");
    }
}

void ProcessEarse::slotsProgress()
{
    if (++m_iValue < 99){
        emit setValue(m_iValue, m_oIcon, _("Blanking..."));
    }
}

void ProcessEarse::slotsRemoveDisc(QString dev)
{
    if(dev == m_oCloneCDROM->device()) {
        if(m_oProcess->state() != QProcess::NotRunning) {
            qDebug() << __func__ << __LINE__ << dev << "被拔出，杀死刻录数据进程";
            LOGGER->info(QString("[%1] [%2] : %3 被拔出，杀死刻录数据进程").arg(__func__).arg(__LINE__).arg(dev));
            m_oProcess->kill();
        }
    }
}

ProcessEarse::~ProcessEarse()
{
    if (auditburner) {
        delete auditburner;
        auditburner = nullptr;
    }

    if (m_oCloneCDROM) {
        delete m_oCloneCDROM;
        m_oCloneCDROM = nullptr;
    }

    LOGGER->info("( ProcessEarse::~ProcessEarse)");
}
