#include "processcopydisk.h"
#include "src/frame/logger.h"
#include "src/po/translation.h"
#include "src/view/modaldialog.h"
#include "src/data/datacdrom.h"
#include "src/frame/signals.h"
#include "src/frame/auditlog.h"
#include <QFileInfo>
#include <kysdk/kysdk-system/libkysysinfo.h>
#include <QDebug>
ProcessCopyDisk::ProcessCopyDisk(void *src, void *des, QObject *parent) :
    ProcessBasic(parent),
    m_oSource(src),
    m_oDestination(des)
{
    DataCDROM *srcCdrom;
    DataCDROM *desCdrom;
    srcCdrom = static_cast<DataCDROM *>(m_oSource);
    desCdrom = static_cast<DataCDROM *>(m_oDestination);
    m_oSrcDeviceBlock = srcCdrom->device();
    m_oDesDeviceBlock = desCdrom->device();
    g_user_signal->setDeviceBusyStatus(m_oSrcDeviceBlock, true);
    g_user_signal->setDeviceBusyStatus(m_oDesDeviceBlock, true);

    LOGGER->registerName(this, _("PROCESS_CD"));
    m_oProcessName = _("Copy Disk");
    title(m_oProcessName);
    setRange(0, 100);
    setValue(0);
    m_fSpeed = 0.0;
}

bool ProcessCopyDisk::prepare()
{
    DataCDROM *src;
    DataCDROM *des;
    QFileInfo f;
    QString sysid;

    m_oProcess->setProgram("/bin/bash");
    m_iProgress = 0;
    src = static_cast<DataCDROM *>(m_oSource);
    des = static_cast<DataCDROM *>(m_oDestination);
    m_oSrcDeviceBlock = src->device();
    m_oDesDeviceBlock = des->device();

    if (sysid.isEmpty()) sysid = _("KylinOS");

    if (src->mediumType().startsWith("CD"))
        f.setFile("/bin/cdrecord");
    else
        f.setFile("/bin/growisofs");
    if (!f.exists() || !f.isExecutable())
    {
        LOGGER->error(_("There is no %1 program or %1 cannot execute."
                "Please check the cdrecord and growisofs is "
                "exists or not, and give the right permissions"
                ".%2 exiting...")
              .arg(f.absoluteFilePath())
              .arg("KylinBurner"));
        return false;
    }

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

    if (des->mediumType().startsWith("CD"))
    {
        m_oMkisofs = QString("genisoimage -r -R -J -joliet-long -no-pad -no-iso-translate ");
        m_oMkisofs.append(QString("-A \"%1\" ").arg(_("KylinBurner")));
        m_oMkisofs.append(QString("-p \"%1\" ").arg(src->settingPreparer()));
        setValue(++m_iProgress, m_oIcon, _("Preparer %1").arg(src->settingPreparer()));
        m_oMkisofs.append(QString("-P \"%1\" ").arg(src->settingPublisher()));
        setValue(++m_iProgress, m_oIcon, _("Publisher %1").arg(src->settingPublisher()));
        m_oMkisofs.append(QString("-copyright \"%1\" ").arg(src->settingCopyright()));
        setValue(++m_iProgress, m_oIcon, _("Copyright %1").arg(src->settingCopyright()));
        m_oMkisofs.append(QString("-V \"%1\" ").arg(src->settingVolumnID()));
        setValue(++m_iProgress, m_oIcon, _("Volumn ID %1").arg(src->settingVolumnID()));
        m_oMkisofs.append(QString("%1").arg(src->mediumMountPoint()));
        if (src->settingSpeed())
            m_oCdrecord = QString("cdrecord -v driveropts=burnfree -nopad -eject dev=%1 speed=%2 ").arg(des->device()).arg(src->settingSpeed());
        else
            m_oCdrecord = QString("cdrecord -v driveropts=burnfree -nopad -eject dev=%1 ").arg(des->device());
        if (src->mediumStatus() == DataMedium::MEDIUM_INCOMPLETE)
            m_oCdrecord.append("-multi -");
        else
            m_oCdrecord.append("-");
        m_oArguments << "-c" << QString("%1 | %2").arg(m_oMkisofs).arg(m_oCdrecord);
    }
    else
    {
        m_oProcess->setProgram(f.fileName());
        m_oArguments << "-J" << "-r" << "-R" << "-joliet-long" << "-no-iso-translate"
                     << "-gui" << "-v" << "-ldots" << "-no-split-symlink-fields"
                     << "-no-cache-inodes" << "-full-iso9660-filenames";
        m_oArguments << "-A" << _("KylinBurner");

        m_oArguments << "-V" << src->settingVolumnID().trimmed();
        LOGGER->debug(_("Volumn ID : %1").arg(m_oArguments.last()));
        setValue(++m_iProgress, m_oIcon, _("Volumn ID %1").arg(m_oArguments.last()));
        m_oArguments << "-p" << src->settingPreparer().trimmed();
        LOGGER->debug(_("Preparer : %1").arg(m_oArguments.last()));
        setValue(++m_iProgress, m_oIcon, _("Preparer %1").arg(m_oArguments.last()));
        m_oArguments << "-P" << src->settingPublisher().trimmed();
        LOGGER->debug(_("Publisher : %1").arg(m_oArguments.last()));
        setValue(++m_iProgress, m_oIcon, _("Publisher %1").arg(m_oArguments.last()));
        m_oArguments << "-copyright" << src->settingCopyright().trimmed();
        LOGGER->debug(_("Copyright : %1").arg(m_oArguments.last()));
        setValue(++m_iProgress, m_oIcon, _("Copyright %1").arg(m_oArguments.last()));
        if (src->mediumStatus() == DataMedium::MEDIUM_FINALIZED)
            m_oArguments << "-dvd-compat";
        m_oArguments << "-Z" << des->device();
        m_oArguments << src->mediumMountPoint();
    }

    return m_oKeep;
}

void ProcessCopyDisk::slotsOutput()
{
    qreal si;
    qreal t;
    qreal basic;
    QString output;
    QStringList s;

    output = m_oProcess->readAllStandardOutput();

    basic = 99 - m_iProgress;

    if (output.contains("Performing OPC"))
    {
        setValue(++m_iProgress, m_oIcon, _("Performing OPC"));
        cancel(false);
    }
    if (output.startsWith("\rTrack"))
    {
        s = output.split(" ");
        for (int i = 0; i < s.size(); ++i)
        {
            if (s.at(i).isEmpty())
            {
                s.takeAt(i);
                --i;
            }
        }
        si = s.at(2).toDouble();
        t = s.at(4).toDouble();
        if (s.size() > 5)
        {
            setValue(m_iProgress + si / t * basic, m_oIcon,
                     _("Writing track %1 speed %2 written %3 %4.")
                     .arg(s.at(1)).arg(s.last()).arg(s.at(2)).arg(s.at(3)));
        }
    }

    if (output.contains("Fixating"))
        setValue(99, m_oIcon, _("Fixating(Will wait minutes)"));
    if (output.contains("Input/output error"))
        m_oKeep = false;
}

void ProcessCopyDisk::slotsError()
{
    qreal v;
    QStringList ss;

    QString output = m_oProcess->readAllStandardError();
    QList<QString> errorInfoList;
    errorInfoList << "Input/output error" << "OPC failed." << "FATAL:" << ":-(" << ":-[";
    bool isErrorInfo = false;

    foreach (QString index, errorInfoList) {
        if(output.contains(index)){
            m_oKeep = false;
            isErrorInfo = true;
            break;
        }
    }

    int basic = 99 - m_iProgress;
    emit cancel(false);

    if (output.contains("done, estimate"))
    {
        output = output.left(output.indexOf('%'));
        v = output.toDouble();
        v = (v / 100.00) * basic;
        m_iProgress += v;

        if (m_iProgress > 99) {
            m_iProgress = 99;
        }

        if (m_fSpeed > 0.000001){
            emit setValue(m_iProgress, m_oIcon, _("Burning by speed %1x").arg(m_fSpeed));
        }

    }
    if (output.contains("Current Write Speed"))
    {
        ss = output.split(" ");
        ss = ss.last().split("x");
        m_fSpeed = ss.first().toDouble();
    }

    if (output.contains("flushing cache"))
    {
        emit setValue(99, m_oIcon, _("flushing cache"));
    }
    if (output.contains("closing track"))
    {
        emit setValue(99, m_oIcon, _("closing track"));
    }
    if (output.contains("closing session"))
    {
        emit setValue(99, m_oIcon, _("closing session"));
    }

    if(isErrorInfo){
        LOGGER->error(output);
    }else{
        LOGGER->info(output);
    }
}

void ProcessCopyDisk::slotsFinished(int errCode, QProcess::ExitStatus status)
{
    bool m_isSpecialMachine;
    //m_isSpecialMachine=kdk_system_is_zyj();
    auditburner = new QGSettings("org.ukui.kylinburner");
    auditlogpath = "/var/log/kylin-burner/os_audit.log";
    m_isSpecialMachine=auditburner->get("burneraudit-isrunning").toBool();
    AuditLog copyDiskLog;
    DataCDROM *dest = (DataCDROM*)m_oDestination;

    LOGGER->info(_("Exit code is %1, status : %2, m_oKeep : %3").arg(errCode).arg(status).arg(m_oKeep));
    if ("cdrecord" == m_oProcess->program())
    {
        if (QProcess::NormalExit == status  && 0 == errCode)
        {
            LOGGER->info(QString("file:[%1] line:[%2] : slotsFinished() CD Medium copy disk success.").arg(__FILE__).arg(__LINE__));
        }
        else
        {
            LOGGER->error(QString("file:[%1] line:[%2] : slotsFinished() CD Medium failure in copy disk. [%3]").arg(__FILE__).arg(__LINE__).arg(m_oProcess->errorString()));
            m_oKeep = false;
        }
    }
    else //DVD
    {
        if (QProcess::NormalExit != status  || errCode != 0)
        {
            m_oKeep = false;
            LOGGER->error(QString("file:[%1] line:[%2] : slotsFinished() DVD Medium have error in copy disk. [%3]").arg(__FILE__).arg(__LINE__).arg(m_oProcess->errorString()));
        } else {
            LOGGER->info(QString("file:[%1] line:[%2] : slotsFinished() DVD Medium copy disk success.").arg(__FILE__).arg(__LINE__));
        }
    }

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

ProcessCopyDisk::~ProcessCopyDisk()
{
    LOGGER->info("( ProcessCopyDisk::~ProcessCopyDisk)");
}
