/***************************************************************************
  dcshellcommandrunner.cpp  -  Valknut Shell Command Runner Implementation
                             -------------------
    begin                : Wed Jul 2 2008
    copyright            : (C) 2008 by Edward Sheldrake
    email                : ejs1920@yahoo.co.uk
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "dcshellcommandrunner.h"

#include <QProcess>
#include <cstdio>

/** */
DCShellCommandRunner::DCShellCommandRunner(QString a, QObject * parent) : QThread(parent) {
    args = a;
    stop = false;
}

/** */
DCShellCommandRunner::~DCShellCommandRunner() {
    cancel();
    /* the longest total sleep in run() is 1.1 seconds */
    if (!wait(1150)) {
        printf("~DCShellCommandRunner: warning not finished\n");
    }
}

/** */
void DCShellCommandRunner::run() {
    QString output;
    bool succeeded = false;
    QProcess process;
    process.start(args);
    process.closeWriteChannel();
    process.waitForFinished(100);

    int i = 0;
    while (((process.state() == QProcess::Starting) || (process.state() == QProcess::Running)) && (i < 2400) && (stop == false)) {
        process.waitForFinished(50);
        i++;
    }

    if (stop) {
        /* just kill the damn process */
        process.terminate();
        QThread::msleep(100);
        process.close();
        if (process.state() != QProcess::NotRunning) {
            process.kill();
            QThread::msleep(100);
        }
        return;
    }

    if ((process.state() == QProcess::NotRunning)) {
        if (process.exitStatus() == QProcess::NormalExit) {
            int exitcode = process.exitCode();
            if (exitcode == 0) {
                output = QString(process.readAllStandardOutput()).trimmed();
                if (output.isEmpty()) {
                    output = tr("Command produced no visible output.");
                } else {
                    succeeded = true;
                }
            } else {
                output = tr("Process exited with status") + " " + QString::number(exitcode);
            }
        } else {
            output = tr("Process was killed or crashed.");
        }
    } else {
        output = tr("Process still running after 2 minutes, killing process...");
        process.terminate();
        QThread::msleep(1000);
        process.close();
        if (process.state() != QProcess::NotRunning) {
            process.kill();
            QThread::msleep(100);
        }
    }

    if (stop == false) // stop is only set to true when things are being deleted
    {
        emit finished(succeeded, output);
    }
}

/** */
void DCShellCommandRunner::cancel() {
    stop = true;
}
