/*
Copyright (c) 2010 by Drake Justice <djustice.kde@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/

#include <QMessageBox>
#include <QProcess>
#include <QFileInfo>
#include <QDebug>

#include <KLocale>

#include "burndataimagethread.h"

BurnDataImageThread::BurnDataImageThread(QObject* parent, const QString& device, const QStringList& files): QThread(parent)
{
    m_fileList = files;
    m_device = device;
    m_hadError = false;
    m_wasCanceled = false;
}

void BurnDataImageThread::run()
{
    connect(&m_timer, SIGNAL(timeout()), this, SLOT(updateProgress()));
    connect(&m_wodimProcess, SIGNAL(finished(int)), this, SLOT(processFinished(int)));
    connect(&m_wodimProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));

    QProcess p;
    p.start("du -sc \"" + m_fileList.join("\" \"") + "\"");
  qDebug() << "du -sc \"" << m_fileList.join("\" \"") << "\"";
    p.waitForFinished();
    QString output = p.readAll();

    m_imageSize = output.split("\n").at(m_fileList.count()).left(6).trimmed().toInt();

    if (m_imageSize < 1024)
        m_imageSize = 1024;

    if (m_imageSize > 850000) {
        qDebug() << "burndataimagethread: error: image is too large for a cd";
    }

    emit dataSize(m_imageSize / 1024);

    m_genisoProcess.setStandardOutputProcess(&m_wodimProcess);
    m_genisoProcess.start("genisoimage -R \"" + m_fileList.join("\" \"") + "\""); // fix me
    m_wodimProcess.start("wodim -gracetime=0 -force -vvv dev=" + m_device + " -");

    m_timer.start(1000);

    exec();
}

void BurnDataImageThread::processFinished(int exit_code)
{
  qDebug() << "processFinished() in burndataimagethread";
    QString output = m_wodimProcess.readAll();
  qDebug() << output;
    m_timer.stop();

    emit finished();

    if (m_hadError)
        return;

    if (m_wasCanceled)
        return;

    if(exit_code == QProcess::NormalExit)
    {
        QMessageBox::information(0, "DiscBurner", i18n("Burning completed"));
    }
    else if (exit_code == QProcess::CrashExit)
    {
        QMessageBox::information(0, "DiscBurner", i18n("Burning failed"));
    }
}

void BurnDataImageThread::processError(QProcess::ProcessError error)
{
  qDebug() << "processError() in burndataimagethread";
    m_hadError = true;

    if (m_wasCanceled)
        return;

    switch(error)
    {
    case 0:
        QMessageBox::information(0, "DiscBurner", i18n("Could not start burning. Check whether you have sufficient permissions."));
        break;

    case 1:
        QMessageBox::information(0, "DiscBurner", i18n("Burning process crashed.  Has valid input been given?"));
        break;

    case 2:
        QMessageBox::information(0, "DiscBurner", i18n("Burning failed: timed out."));
        break;

    case 3:
        QMessageBox::information(0, "DiscBurner", i18n("Burning failed: cannot communicate with burning process."));
        break;

    case 4:
        QMessageBox::information(0, "DiscBurner", i18n("Burning failed due to a write error. Check disk space and permissions."));
        break;

    case 5:
        QMessageBox::information(0, "DiscBurner", i18n("Burning failed with an unknown error."));
        break;
    };
}

void BurnDataImageThread::updateProgress()
{
  qDebug() << "updateProgress() in burndataimagethread";
    QString output = m_wodimProcess.readAll();
    const QStringList lines = output.split('\n');
  qDebug() << output;

    if (output.contains("exclusively (Device or resource busy)...")) {
        m_hadError = true;
        cancelProcess();
        QMessageBox::information(0, i18n("Error"), i18n("The disc is either mounted or in use. discburner will not burn on it."));
    } else if (output.contains("WARNING: Data may not fit")) {
        m_hadError = true;
        cancelProcess();
        QMessageBox::information(0, i18n("Error"), i18n("The disc is either too small, or the image is too big. ;)"));
    }

    foreach (const QString& line, lines) {
        if (line.contains("written (fifo")) {
            emit dataProgress(line.split(' ', QString::SkipEmptyParts).at(2).toInt());
        } else if (line.contains("Fixating...")) {
            emit dataProgress(m_imageSize / 1024);
        }
    }
}

void BurnDataImageThread::cancelProcess()
{
    m_wasCanceled = true;
    m_wodimProcess.kill();
}
