/***************************************************************************
 *   Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org>                  *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/
#ifndef PROCESS_H
#define PROCESS_H

#include <signal.h>
#include <tqstringlist.h>
#include <tqobject.h>
#include <tqtimer.h>
class KProcess;

#include "global.h"
namespace PURL { class Directory; }

namespace Process
{
enum State { Stopped, StartFailed, Running, Exited, Timedout };
class Base;
enum RunAction { NoRunAction = 0, Start = 1 };
TQ_DECLARE_FLAGS(RunActions, RunAction)
TQ_DECLARE_OPERATORS_FOR_FLAGS(RunActions)
extern State runSynchronously(Base &process, RunActions actions, uint timeout); // in ms (0 == no timeout)

//----------------------------------------------------------------------------
class Base : public TQObject
{
Q_OBJECT
  TQ_OBJECT
public:
  Base(TQObject *parent, const char *name);
  virtual ~Base();
  void setup(const TQString &executable, const TQStringList &options, bool withWine);
  TQStringList arguments() const;
  void setWorkingDirectory(const PURL::Directory &dir);
  void setUseShell(bool useShell);
  virtual bool start(uint timeout); // in ms (0 == no timeout)
  TQString prettyCommand() const { return arguments().join(" "); }
  void writeToStdin(const TQString &s);
  bool signal(int n);
  bool isRunning() const;
  State state() const { return _state; }
  int exitCode() const;

signals:
  void requestSynchronousStop();
  void done(int code);
  void timeout();
  void stdoutDataReceived();
  void stderrDataReceived();

protected slots:
  void exited();
  void timeoutSlot();
  virtual void receivedStdout(KProcess*, char *buffer, int len) = 0;
  virtual void receivedStderr(KProcess*, char *buffer, int len) = 0;

  friend State runSynchronously(Base &, RunActions, uint);

protected:
  State     _state;
  KProcess *_process;
  TQTimer   *_timer;
  TQString   _stdout, _stderr;

  static bool isFilteredLine(const TQString &line);
};

//----------------------------------------------------------------------------
class StringOutput : public Base
{
Q_OBJECT
  TQ_OBJECT
public:
  StringOutput(TQObject *parent = 0, const char *name = 0) : Base(parent, name) {}
  TQString sout() const { return _stdout; }
  TQString serr() const { return _stderr; }

private slots:
  virtual void receivedStdout(KProcess *, char *buffer, int len);
  virtual void receivedStderr(KProcess *, char *buffer, int len);
};

//----------------------------------------------------------------------------
class LineBase : public Base
{
Q_OBJECT
  TQ_OBJECT
public:
  LineBase(TQObject *parent = 0, const char *name = 0) : Base(parent, name) {}

private slots:
  virtual void receivedStdout(KProcess *, char *buffer, int len);
  virtual void receivedStderr(KProcess *, char *buffer, int len);

private:
  virtual void addStdoutLine(const TQString &line) = 0;
  virtual void addStderrLine(const TQString &line) = 0;
};

//----------------------------------------------------------------------------
class LineOutput : public LineBase
{
Q_OBJECT
  TQ_OBJECT
public:
  LineOutput(TQObject *parent = 0, const char *name = 0) : LineBase(parent, name) {}
  virtual bool start(uint timeout);
  TQStringList sout() const { return _stdoutLines; }
  TQStringList serr() const { return _stderrLines; }

protected:
  TQStringList _stdoutLines, _stderrLines;

  virtual void addStdoutLine(const TQString &line) { _stdoutLines += line; }
  virtual void addStderrLine(const TQString &line) { _stderrLines += line; }
};

//----------------------------------------------------------------------------
class LineSignal : public LineBase
{
Q_OBJECT
  TQ_OBJECT
public:
  LineSignal(TQObject *parent = 0, const char *name = 0) : LineBase(parent, name) {}

signals:
  void logStdoutLine(const TQString &line);
  void logStderrLine(const TQString &line);

private:
  virtual void addStdoutLine(const TQString &line) { emit logStdoutLine(line); }
  virtual void addStderrLine(const TQString &line) { emit logStderrLine(line); }
};

} // namespace

#endif
