#include "processbasic.h"
#include "src/frame/logger.h"
#include "src/frame/configuration.h"
#include "src/po/translation.h"
#include "src/view/modaldialog.h"
#include "src/view/tip_burnresult.h"
#include "src/model/logicmain.h"
#include <QStandardPaths>
#include <QCoreApplication>

ProcessBasic::ProcessBasic(QObject *parent) :
    QObject(parent),
    m_oProcess(new QProcess(this)),
    m_bCancel(false),
    m_u32Icon(0),
    m_oIcon(QIcon::fromTheme("ukui-loading-0")),
    m_oTimer(new QTimer(this))
{
    m_oProcessName.clear();
    m_oArguments.clear();
    connect(this, SIGNAL(info(QString)), LOGGER, SLOT(info(QString)));
    connect(this, SIGNAL(warn(QString)), LOGGER, SLOT(warn(QString)));
    connect(this, SIGNAL(error(QString)), LOGGER, SLOT(error(QString)));
    connect(this, SIGNAL(debug(QString)), LOGGER, SLOT(debug(QString)));
    connect(m_oTimer, SIGNAL(timeout()), this, SLOT(slotsIcon()));
    connect(MODAL, SIGNAL(rejected()), this, SLOT(slotsCancel()));
    connect(this, SIGNAL(title(QString)), PROGRESS, SIGNAL(title(QString)));
    connect(this, SIGNAL(setRange(int,int)), PROGRESS, SIGNAL(setRange(int, int)));
    connect(this, SIGNAL(setValue(int,QIcon,QString)), PROGRESS, SIGNAL(setValue(int,QIcon,QString)));
    connect(this, SIGNAL(addValue(int,QIcon,QString)), PROGRESS, SIGNAL(addValue(int,QIcon,QString)));
    connect(this, SIGNAL(updateIcon(QIcon)), PROGRESS, SLOT(slotsUpdateIcon(QIcon)));

    connect(this, SIGNAL(success(QString)), TIP_BURNRESULT, SLOT(slotsSuccess(QString)));
    connect(this, SIGNAL(fail(QString)), TIP_BURNRESULT, SLOT(slotsFailed(QString)));
    connect(this, SIGNAL(title(QString)), TIP_BURNRESULT, SLOT(slotsTitle(QString)));
    connect(MAIN, SIGNAL(exit()), this, SLOT(slotsExit()));
}

void ProcessBasic::exec()
{
    bool result;
    int step;

    m_lastErrorMsg = "";
    m_oKeep = true;
    step = Prepare;
    result = true;
    m_bCancel = false;

    connection();

    //m_oTimer->setInterval(1);
    //m_oTimer->start();
    while (!m_bCancel && m_oKeep && step <= Worked)
    {
        switch (step++)
        {
        case Prepare:
            m_oKeep = prepare();
            info(QString("file:[%1] line:[%2] : prepare() end. m_okeep=[%3]").arg(__FILE__).arg(__LINE__).arg(m_oKeep));
            break;
        case Config:
            m_oKeep = config();
            if(_("Earse") == m_oProcessName)
                disconnect(MODAL, SIGNAL(rejected()), this, SLOT(slotsCancel()));
            info(QString("file:[%1] line:[%2] : Config() end. m_okeep=[%3]").arg(__FILE__).arg(__LINE__).arg(m_oKeep));
            break;
        case Working:
            m_oKeep = working();
            info(QString("file:[%1] line:[%2] : Working() end. m_okeep=[%3]").arg(__FILE__).arg(__LINE__).arg(m_oKeep));
            break;
        case Worked:
            m_oKeep = worked();
            info(QString("file:[%1] line:[%2] : Worked() end. m_okeep=[%3]").arg(__FILE__).arg(__LINE__).arg(m_oKeep));
            break;
        default:
            break;
        }
    }
    m_oTimer->stop();
    disconnect(this, SIGNAL(cancel(bool)), MODAL, SLOT(cancelEnable(bool)));
    QString UserPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    QString strUsr = UserPath.section("/",-1,-1);

    if (m_bCancel)
    {
        debug(_("User canceled."));
        QString strDes;
        if(m_oArguments.count() >= 2)
        {
            strDes = m_oArguments.at(1);
        }
        info(QString("file:[%1] line:[%2] User-Canel : m_bCancel = [%3]. User canceled in Burn process. Burn process failure").arg(__FILE__).arg(__LINE__).arg(m_bCancel));
        info(_("User") + "=" + strUsr + " , " + _("Destination") + "=" + strDes + " , " + _("Burn result") + "=" + m_oProcessName +" " + _("KylinBurner") + _("User canceled."));
        fail(m_oProcessName);
        MODAL->hide();
        eject();
        result = false;
        return;
    }
    if (!m_oKeep)
    {
        result = false;
        error(QString("file:[%1] line:[%2] BurningProcessError : m_oKeep = [%3]. The burn process is interrupted or error. Burn process failure").arg(__FILE__).arg(__LINE__).arg(m_oKeep));
        error(_("Step.%1 error happened.").arg(--step));
        QString strDes;
        if(m_oArguments.count() >= 2)
        {
            strDes = m_oArguments.at(1);
        }
        info(_("User") + "=" + strUsr + " , " + _("Destination") + "=" + strDes + " , " + _("Burn result") + "=" + m_oProcessName +" " + _("KylinBurner") + _(" Failed"));
        if (m_lastErrorMsg.isEmpty()) {
            fail(m_oProcessName);
        } else {
            fail(m_lastErrorMsg + m_oProcessName);
            m_lastErrorMsg = "";
        }
        MODAL->hide();
        eject();
        return;
    }

    if (m_oProcessName == _("load") || m_oProcessName == _("Media Info")) return;
    QString strDes;
    if(m_oArguments.count() >= 2)
    {
        strDes = m_oArguments.at(1);
    }
    info(_("User") + "=" + strUsr + " , " + _("Destination") + "=" + strDes + " , " + _("Burn result") + "=" + m_oProcessName +" " + _("KylinBurner") + _(" Success"));
    info(QString("file:[%1] line:[%2] BurningProcessSuccess : m_bCancel = [%3], m_oKeep = [%4]. Burn process Success").arg(__FILE__).arg(__LINE__).arg(m_bCancel).arg(m_oKeep));
    success(m_oProcessName);
    MODAL->hide();
}

bool ProcessBasic::prepare()
{
    return m_oKeep;
}

bool ProcessBasic::config()
{
    return m_oKeep;
}

bool ProcessBasic::working()
{
    info(_("Argument setted for %1:").arg(m_oProcess->program()));
    for (int i = 0; i < m_oArguments.size(); ++i)
    {
        info(_("Arg.%1 - %2").arg(i + 1).arg(m_oArguments.at(i)));
    }
    if (m_bCancel) return false;
    m_oProcess->setArguments(m_oArguments);
    m_oProcess->start();
    debug(_("Process started"));
    for (int i = 0;  i < m_oArguments.size(); ++i)
        debug(_("Arg.%1 : %2").arg(i + 1).arg(m_oArguments.at(i)));
    info(_("starting process %1").arg(m_oProcess->program()));
    while (m_oProcess->state() != QProcess::NotRunning)
        QCoreApplication::processEvents();
    return m_oKeep;
}

bool ProcessBasic::worked()
{
    return m_oKeep;
}

void ProcessBasic::slotsCancel()
{
    if (m_bCancel) return;
    m_bCancel = true;
    if(m_oProcessName==_("Media Info")){
        m_bCancel=false;
        return;
    }
    if (m_oProcess->state() != QProcess::NotRunning)
    {
        debug(_("Stop process when user canceled."));
        m_oProcess->kill();
    }
    if (!m_oKeep) debug(_("User canceled."));
}

void ProcessBasic::slotsIcon()
{
    m_oIcon = QIcon::fromTheme(QString("ukui-loading-%1").arg((m_u32Icon++) % 8));
    updateIcon(m_oIcon);
}

void ProcessBasic::slotsExit()
{
    m_oProcess->kill();
}

void ProcessBasic::connection()
{
    connect(m_oProcess, SIGNAL(started()), this, SLOT(slotsStart()));
    connect(m_oProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(slotsOutput()));
    connect(m_oProcess, SIGNAL(readyReadStandardError()), this, SLOT(slotsError()));
    connect(m_oProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotsFinished(int,QProcess::ExitStatus)));
}

ProcessBasic::~ProcessBasic()
{}
