#include "processinvoker.hpp"
#include 
#include 
#include 
#include 
#if defined(Q_OS_MAC)
#include 
#endif
Process::ProcessInvoker::ProcessInvoker(QObject* parent)
    : QObject(parent)
{
    mProcess = new QProcess(this);
    connect(mProcess, &QProcess::errorOccurred, this, &ProcessInvoker::processError);
    connect(
        mProcess, qOverload(&QProcess::finished), this, &ProcessInvoker::processFinished);
    mName = QString();
    mArguments = QStringList();
}
Process::ProcessInvoker::~ProcessInvoker() {}
// void Process::ProcessInvoker::setProcessName(const QString &name)
//{
//     mName = name;
// }
// void Process::ProcessInvoker::setProcessArguments(const QStringList &arguments)
//{
//     mArguments = arguments;
// }
QProcess* Process::ProcessInvoker::getProcess()
{
    return mProcess;
}
// QString Process::ProcessInvoker::getProcessName()
//{
//     return mName;
// }
// QStringList Process::ProcessInvoker::getProcessArguments()
//{
//     return mArguments;
// }
bool Process::ProcessInvoker::startProcess(const QString& name, const QStringList& arguments, bool detached)
{
    //    mProcess = new QProcess(this);
    mName = name;
    mArguments = arguments;
    mIgnoreErrors = false;
    QString path(name);
#ifdef Q_OS_WIN
    path.append(QLatin1String(".exe"));
#elif defined(Q_OS_MAC)
    QDir dir(QCoreApplication::applicationDirPath());
    path = dir.absoluteFilePath(name);
#else
    path.prepend(QLatin1String("./"));
#endif
    QFileInfo info(path);
    if (!info.exists())
    {
        QMessageBox msgBox;
        msgBox.setWindowTitle(tr("Error starting executable"));
        msgBox.setIcon(QMessageBox::Warning);
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setText(
            tr("Could not find %1
 \
                          The application is not found.
 \
                          Please make sure OpenMW is installed correctly and try again.
")
                .arg(info.fileName()));
        msgBox.exec();
        return false;
    }
    if (!info.isExecutable())
    {
        QMessageBox msgBox;
        msgBox.setWindowTitle(tr("Error starting executable"));
        msgBox.setIcon(QMessageBox::Warning);
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setText(
            tr("Could not start %1
 \
                          The application is not executable.
 \
                          Please make sure you have the right permissions and try again.
")
                .arg(info.fileName()));
        msgBox.exec();
        return false;
    }
    // Start the executable
    if (detached)
    {
        if (!mProcess->startDetached(path, arguments))
        {
            QMessageBox msgBox;
            msgBox.setWindowTitle(tr("Error starting executable"));
            msgBox.setIcon(QMessageBox::Critical);
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setText(
                tr("Could not start %1
 \
                              An error occurred while starting %1.
 \
                              Press \"Show Details...\" for more information.
")
                    .arg(info.fileName()));
            msgBox.setDetailedText(mProcess->errorString());
            msgBox.exec();
            return false;
        }
    }
    else
    {
        mProcess->start(path, arguments);
        /*
        if (!mProcess->waitForFinished()) {
            QMessageBox msgBox;
            msgBox.setWindowTitle(tr("Error starting executable"));
            msgBox.setIcon(QMessageBox::Critical);
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setText(tr("Could not start %1
 \
                              An error occurred while starting %1.
 \
                              Press \"Show Details...\" for more
        information.
").arg(info.fileName())); msgBox.setDetailedText(mProcess->errorString());
            msgBox.exec();
            return false;
        }
        if (mProcess->exitCode() != 0 || mProcess->exitStatus() == QProcess::CrashExit) {
            QString error(mProcess->readAllStandardError());
            error.append(tr("\nArguments:\n"));
            error.append(arguments.join(" "));
            QMessageBox msgBox;
            msgBox.setWindowTitle(tr("Error running executable"));
            msgBox.setIcon(QMessageBox::Critical);
            msgBox.setStandardButtons(QMessageBox::Ok);
            msgBox.setText(tr("Executable %1 returned an error
 \
                              An error occurred while running %1.
 \
                              Press \"Show Details...\" for more
        information.
").arg(info.fileName())); msgBox.setDetailedText(error); msgBox.exec();
            return false;
        }
        */
    }
    return true;
}
void Process::ProcessInvoker::processError(QProcess::ProcessError error)
{
    if (mIgnoreErrors)
        return;
    QMessageBox msgBox;
    msgBox.setWindowTitle(tr("Error running executable"));
    msgBox.setIcon(QMessageBox::Critical);
    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setText(
        tr("
Executable %1 returned an error
 \
                      An error occurred while running %1.
 \
                      Press \"Show Details...\" for more information.
")
            .arg(mName));
    msgBox.setDetailedText(mProcess->errorString());
    msgBox.exec();
}
void Process::ProcessInvoker::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    if (exitCode != 0 || exitStatus == QProcess::CrashExit)
    {
        if (mIgnoreErrors)
            return;
        QString error(mProcess->readAllStandardError());
        error.append(tr("\nArguments:\n"));
        error.append(mArguments.join(" "));
        QMessageBox msgBox;
        msgBox.setWindowTitle(tr("Error running executable"));
        msgBox.setIcon(QMessageBox::Critical);
        msgBox.setStandardButtons(QMessageBox::Ok);
        msgBox.setText(
            tr("Executable %1 returned an error
 \
                          An error occurred while running %1.
 \
                          Press \"Show Details...\" for more information.
")
                .arg(mName));
        msgBox.setDetailedText(error);
        msgBox.exec();
    }
}
void Process::ProcessInvoker::killProcess()
{
    mIgnoreErrors = true;
    mProcess->kill();
}