/***************************************************************************
  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;
}
