/*
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 <QFileInfo>
#include <QMessageBox>
#include <QProcess>
#include <QDebug>

#include <KLocale>

#include "convertthread.h"

ConvertThread::ConvertThread(QObject* parent, const QStringList& filenames, const QString& format): QThread(parent)
{
    m_filenames = filenames;
    m_cNumber = 0;
    m_format = format;
    m_hadError = false;
    m_wasCanceled = false;
    m_foundTotalFrames = false;
    m_process.setProcessChannelMode(QProcess::MergedChannels);
}

void ConvertThread::run()
{
  qDebug() << "ConvertThread::run()";
    connect(&m_timer, SIGNAL(timeout()), this, SLOT(updateProgress()));
    connect(&m_process, SIGNAL(finished(int)), this, SLOT(processFinished(int)));
    connect(&m_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));

    if (m_format == "audiocd_wav") {
        if (m_filenames.at(m_cNumber).right(3).toLower() == "mp3") {
            m_process.start("mpg123 --smooth -v -w \"/tmp/discburner_audioproject/" + QFileInfo(m_filenames.at(m_cNumber)).baseName() + ".wav\" \"" + m_filenames.at(m_cNumber) + "\"");
        } else if ( m_filenames.at(m_cNumber).right(3).toLower() == "ogg" ) {
            m_process.start("oggdec -R \"" + m_filenames.at(m_cNumber) + "\" -o \"/tmp/discburner_audioproject/" + QFileInfo(m_filenames.at(m_cNumber)).baseName() + ".wav\"");
        } else if ( m_filenames.at(m_cNumber).right(4).toLower() == "flac" ) {
            m_process.start("flac -df -8 \"" + m_filenames.at(m_cNumber) + "\" -o \"/tmp/discburner_audioproject/" + QFileInfo(m_filenames.at(m_cNumber)).baseName() + ".wav\"");
        }
    } else if (m_format == "to_mp3")  {
        foreach (QString file, m_filenames) { // huh? redo this
            if (m_filenames.at(m_cNumber).right(3).toLower() == "mp3") {
                m_filenames.removeOne(file);
            }
        }

        if (m_filenames.isEmpty()) {
            m_process.start("ps"); // fix meh
        } else {
            if (m_filenames.at(m_cNumber).right(3).toLower() != "mp3") {
                m_process.start("sox --magic -S -V6 \"" + m_filenames.at(m_cNumber) + "\" \"/tmp/discburner_mp3cdproject/" + QFileInfo(m_filenames.at(m_cNumber)).baseName() + ".mp3\"");
            }
        }
    }

    m_timer.start(1000);

    if (!m_filenames.isEmpty()) {
        currentFile(QFileInfo(m_filenames.at(m_cNumber)).baseName());
    }

    exec();
}

void ConvertThread::processFinished(int exit_code)
{
  qDebug() << "processFinished() exit_code: " << exit_code;

    if (m_hadError)
        return;

    if (m_wasCanceled)
        return;

    if(m_cNumber == m_filenames.count() - 1 || m_filenames.isEmpty()) {
        m_timer.stop();
        emit beginBurning();
        return;
    }

    m_cNumber++;
    m_foundTotalFrames = false;

    if(m_format == "audiocd_wav") {
        if( m_filenames.at(m_cNumber).right(3).toLower() == "mp3" ) {
            m_process.start("mpg123 --aggressive -v -w \"/tmp/discburner_audioproject/" + QFileInfo(m_filenames.at(m_cNumber)).baseName() + ".wav\" \"" + m_filenames.at(m_cNumber) + "\"");
        } else if ( m_filenames.at(m_cNumber).right(3).toLower() == "ogg" ) {
            m_process.start("oggdec -R \"" + m_filenames.at(m_cNumber) + "\" -o \"/tmp/discburner_audioproject/" + QFileInfo(m_filenames.at(m_cNumber)).baseName() + ".wav\"");
        } else if ( m_filenames.at(m_cNumber).right(4).toLower() == "flac" ) {
            m_process.start("flac -df --no-verify \"" + m_filenames.at(m_cNumber) + "\" -o \"/tmp/discburner_audioproject/" + QFileInfo(m_filenames.at(m_cNumber)).baseName() + ".wav\"");
        }
    } else if (m_format == "to_mp3")  {
        if (m_filenames.at(m_cNumber).right(3).toLower() != "mp3") {
            m_process.start("sox --magic -S -V6 \"" + m_filenames.at(m_cNumber) + "\" \"/tmp/discburner_mp3cdproject/" + QFileInfo(m_filenames.at(m_cNumber)).baseName() + ".mp3\"");
        }
    }

    emit currentFile(QFileInfo(m_filenames.at(m_cNumber)).baseName());
}

void ConvertThread::processError(QProcess::ProcessError error)
{
    m_hadError = true;

    if (m_wasCanceled)
        return;

    switch(error)
    {
    case 0:
        QMessageBox::information(0, "DiscBurner", i18n("Could not start converting. Check whether you have sufficient permissions and all needed dependencies (mpg123/sox/lame/flac/oggdec/etc)."));
        break;

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

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

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

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

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

void ConvertThread::updateProgress()
{
    QString output = m_process.readAll();
  qDebug() << "updateProgress() m_process::output: " << output;
    if (m_format == "audiocd_wav") {
        foreach (QString line, output.split("\n", QString::SkipEmptyParts)) {
            if (m_filenames.at(m_cNumber).right(3).toLower() == "mp3") {
                if (line.contains("Frame#")) {
                    if (!line.split(" ", QString::SkipEmptyParts).at(1).isEmpty()) {
                        if (!m_foundTotalFrames) {
                            emit totalFrames(line.replace("]", " ").replace("[", " ").split(" ", QString::SkipEmptyParts).at(2).toInt());
                            m_foundTotalFrames = true;
                        }
                        emit currentFrame(line.split(" ", QString::SkipEmptyParts).at(1).split("/", QString::SkipEmptyParts).at(0).toInt());
                    }
                }
            } else if (m_filenames.at(m_cNumber).right(3).toLower() == "ogg") {
                if (line.contains("%]")) {
                    emit totalFrames(100);
                    emit currentFrame(line.replace("[", " ").replace("]", " ").split(".", QString::SkipEmptyParts).at(0).toInt());
                }
            } else if (m_filenames.at(m_cNumber).right(4).toLower() == "flac") {
                if (line.contains(QFileInfo(m_filenames.at(m_cNumber)).baseName())) {
                    emit totalFrames(100);
                    QString m_line = line.replace(QFileInfo(m_filenames.at(m_cNumber)).baseName(), " ").split(' ', QString::SkipEmptyParts).at(2); // violent =[
                    emit currentFrame(m_line.replace("%", " ").trimmed().toInt());
                }
            }
        }
    } else if (m_format == "to_mp3") {
        emit totalFrames(100);
        foreach (QString line, output.split("\n")) {
            if (line.contains("In:")) {
                QString p = line.split(" ").at(0);
                QString q = p.split(":").at(1);
                emit currentFrame(q.split(".").at(0).toInt());
            }
        }
    }
}

void ConvertThread::cancelProcess()
{
    m_wasCanceled = true;
    m_process.kill();
    m_timer.stop();
    emit finished();
}
