#include "processcreateiso.h"
#include "src/frame/logger.h"
#include "src/po/translation.h"
#include "src/data/datacdrom.h"
#include "src/data/datadirectory.h"
#include "src/view/modaldialog.h"
#include "src/view/execdialog.h"

#include <QFileInfo>
#include <fstream>
#include <QStorageInfo>

ProcessCreateISO::ProcessCreateISO(void *r, void *d, QObject *parent) :
    ProcessBasic(parent)
{
    m_oRoot = r;
    m_oCDROM = d;
    LOGGER->registerName(this, _("PROCESS_CI"));
    m_oProcessName = _("Creating ISO");
    title(m_oProcessName);
    setRange(0, 100);
    setValue(0);
  //  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();
}

bool ProcessCreateISO::prepare()
{
    DataCDROM *cdrom;
    DataDirectory *root;
    ifstream fin;
    QFileInfo f;
    QString sysid;
    std::string s;

    cdrom = (DataCDROM *)(m_oCDROM);
    root = (DataDirectory *)(m_oRoot);
    PROGRESS;
    MODAL->show();
    connect(this, SIGNAL(cancel(bool)), MODAL, SLOT(cancelEnable(bool)));

    f.setFile("/bin/mkisofs");
    if (!f.exists())
    {
        error(_("Cannot find program <%1>.").arg(f.fileName()));
        setValue(1, QIcon::fromTheme("dialog-error-symbolic"),
                 _("Cannot find program <%1>.").arg(f.fileName()));
        return false;
    }
    if (!f.isExecutable())
    {
        error(_("Program %1 is not executable file.").arg(f.fileName()));
        setValue(1, QIcon::fromTheme("dialog-error-symbolic"),
                 _("Program %1 is not executable file.").arg(f.fileName()));
        return false;
    }
    setValue(1, m_oIcon, _("Checking program %1 can be supported.").arg(m_oProcess->program()));
    m_oProcess->setProgram(f.fileName());
    f.setFile(cdrom->mDisplay());
    if (f.exists())
    {
        if (!EXEC->question(_("Create ISO") + " - " + _("Already Exists"),
                           _("There is already have the iso file named %1,"
                             "replace it or not?").arg(f.fileName())))
            return false;
        if (f.isFile()) QFile::remove(f.absoluteFilePath());
        else { QDir dir(f.absoluteFilePath()); dir.removeRecursively(); }
    }
    m_oArguments << "-o" << cdrom->mDisplay();
    setValue(2, m_oIcon, _("Ready to create %1 file.").arg(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") << "-sysid";
    fin.open("/etc/kylin-build");
    if (fin.is_open())
    {
        std::getline(fin, s);
        sysid = QString::fromStdString(s);
    }
    if (sysid.isEmpty()) sysid = _("KylinOS");
    m_oArguments << sysid;
    setValue(3, m_oIcon, _("Initlized default arguments."));
    if (root->size() > 2UL * 1024UL * 1024UL * 1024UL)
    {
        debug(_("%1 data size more than 2 GB, need allow-limited-size "
                "extension").arg(_("CreateISO")));
        m_oArguments << "-allow-limited-size";
    }
    setValue(4, m_oIcon, _("%1 check need allow-limited-size extension "
                                     "or not").arg(_("CreateISO")));
    if (root->size() > 4UL * 1024UL * 1024UL * 1024UL)
    {
        debug(_("%1 data size more than 4 GB, need UDF extension")
              .arg(_("CreateISO")));
        m_oArguments << "-udf";
    }
    setValue(5, m_oIcon, _("%1 check need UDF extension or not").arg(_("CreateISO")));
    return true;
}

bool ProcessCreateISO::config()
{
    DataCDROM *cdrom;
    DataDirectory *root;
    QStorageInfo storage;

    cdrom = (DataCDROM *)(m_oCDROM);
    root = (DataDirectory *)(m_oRoot);

    m_oArguments << "-V" << cdrom->settingVolumnID();
    setValue(6, m_oIcon, _("Setted volumn ID : %1").arg(m_oArguments.last()));
    debug(_("Volumn ID : %1").arg(m_oArguments.last()));
    m_oArguments << "-p" << cdrom->settingPreparer();
    setValue(7, m_oIcon, _("Setted preparer : %1").arg(m_oArguments.last()));
    debug(_("Preparer : %1").arg(m_oArguments.last()));
    m_oArguments << "-P" << cdrom->settingPublisher();
    setValue(8, m_oIcon, _("Setted publisher : %1").arg(m_oArguments.last()));
    debug(_("Publisher : %1").arg(m_oArguments.last()));
    m_oArguments << "-copyright" << cdrom->settingCopyright();
    setValue(9, m_oIcon, _("Setted copyright : %1").arg(m_oArguments.last()));
    debug(_("Copyright : %1").arg(m_oArguments.last()));
    storage.setPath(cdrom->settingTempPath());
    if (!storage.isValid())
    {
        error(_("Invalid temporary storage path."));
        return false;
    }
    if (root->size() > storage.bytesAvailable())
    {
        error(_("Temporary storage has not enough space for create iso."));
        return false;
    }
    setValue(10, m_oIcon, _("Check storage space over."));
    // copy file.
    m_iCopied = 0;
    connect(root, SIGNAL(copied(QString,QString)), this, SLOT(slotsCopy(QString,QString)));
    root->copy();
    debug(_("Need to copy %1 file(s)").arg(root->total()));
    if (m_bCancel) return false;
    m_oArguments << root->destination();
    cancel(false);
    return true;
}
bool ProcessCreateISO::worked()
{
    DataCDROM *cdrom;
    DataDirectory *root;
    QDir dir;
    QFileInfo f;

    if (m_bCancel) return false;
    if (QProcess::NormalExit != m_oProcess->exitStatus()) return false;
    cdrom = static_cast<DataCDROM *>(m_oCDROM);
    root = static_cast<DataDirectory *>(m_oRoot);
    dir.setPath(root->destination());
    dir.removeRecursively();
    if (cdrom->settingClean()) clear();
    f.setFile(cdrom->mDisplay());
    if (cdrom->settingOpen())
        system(QString("peony -i %1").arg(f.absoluteFilePath()).toUtf8().data());
    return true;
}

void ProcessCreateISO::slotsStart()
{
    setValue(8, m_oIcon, _("Started Create ISO"));
    debug(_("Create ISO started."));
}

void ProcessCreateISO::slotsOutput()
{}

void ProcessCreateISO::slotsError()
{
    QString output;
    int v;

    v = 0;

    output = m_oProcess->readAllStandardError();
    if (output.contains("done, estimate")) // 2.50% done, estimate finish Tue Feb  2 17:15:15 2021
    {
        output = output.left(output.indexOf('%'));
        // 100 - 55 - 1 = 44
        v = output.toDouble();
        v = (v / 100.00) * 49;
        setValue(50 + v, m_oIcon, _("Creating ISO"));
    }
    debug(output);
}

void ProcessCreateISO::slotsFinished(int code, QProcess::ExitStatus status)
{
    info(_("Exit code is %1, status : %2").arg(code).arg(status));
    setValue(99, m_oIcon, _("Creating ISO"));
    if (QProcess::NormalExit == status && 0 == code)
    {
        setValue(100, m_oIcon, _("Created ISO"));
        info( QString("file:[%1] line:[%2] : slotsFinished() create ISO success.").arg(__FILE__).arg(__LINE__) );
    }
    else
    {
        m_oKeep = false;
        error( QString("file:[%1] line:[%2] : slotsFinished() create ISO failure. [%3]").arg(__FILE__).arg(__LINE__).arg(m_oProcess->errorString()) );
    }

    DataCDROM* cdrom = (DataCDROM*)m_oCDROM;
    if(m_isSpecialMachine==true){
        auditburner->set("burner-os-auditlog-name",auditlogpath);
    m_oCreateIsoLog.ouputCreateResult(cdrom->display(), cdrom->mDisplay(), true==m_oKeep);
    }else{
        auditburner->set("burner-os-auditlog-name","");
    }
}

void ProcessCreateISO::slotsCopy(QString src, QString des)
{
    int v;
    DataDirectory *root;

    root = (DataDirectory *)(m_oRoot);
    m_oCreateIsoLog.appendFile(src);                        //待刻录的源文件
    v = 0;

    ++m_iCopied;
    v = ((m_iCopied * 1.0) / (root->total() * 1.0));
    v = (v / 100.00) * 40;
    setValue(10 + v, m_oIcon, _("Copied %1 to %2").arg(src).arg(des));
    debug(_("Copied %1 to %2").arg(src).arg(des));
}

ProcessCreateISO::~ProcessCreateISO()
{}
