#ifndef QTDPUSER_H
#define QTDPUSER_H

#include <QWidget>
#include <QLineEdit>
#include <QStringList>
#include <QStatusBar>
#include <QLabel>
#include <QString>
#include <QThread>
#include <QTextEdit>
#include <QEvent>
#include <QMutex>
#include <iostream>
#include <streambuf>
#include <sstream>

#include <QTemporaryFile>



//#include "QFitsGlobal.h"
#include "guitools.h"

extern QMutex *dpusermutex;
extern QMutex *qtinputmutex;
extern QStringList qtinput;
extern bool DPUSERbusy;

class dpuser_thread : public QThread {
    Q_OBJECT
public:
    virtual void run();
    void dosleep(int i) { msleep(i); }
    void sendText(const QString &text) { emit dpuserText(text); }
    void sendProgress(const int &onWhich, const char *onText) {
        emit dpuserProgress(onWhich, QString(onText));
    }
    void sendHelp(const QString &request) { emit dpuserHelp(request); }
    void sendVar(const std::string &which);
    void sendView(const std::string &which);
    void sendCommand(const char *what, const char *args, const int &option);
    void sendPgplot(const int &which, const QImage &image) { emit pgplotUpdate(which, image); }
    void sendPgplot(const int &which, const int &w, const int &h) { emit pgplotUpdate(which, w, h); }
signals:
    void dpuserText(const QString &);
    void dpuserProgress(const int &onWhich, const QString &onText);
    void dpuserHelp(const QString &);
    void dpuserVar(const std::string &which);
    void dpuserView(const std::string &which);
    void dpuserCommand(const QString &cmd, const QString &arg, const int &option);
    void pgplotUpdate(const int &which, const QImage &image);
    void pgplotUpdate(const int &which, const int &w, const int &h);
};

extern dpuser_thread dpuserthread;

class dpuserOutput : public QTextEdit {
    Q_OBJECT
public:
    dpuserOutput(QWidget *);
protected:
    virtual void focusInEvent(QFocusEvent *e);
    virtual void dropEvent(QDropEvent *e);
    virtual void mouseReleaseEvent(QMouseEvent *);
signals:
    void pasteRequested();
    void pasteSelectionRequested();
public slots:
    void paste();
};

extern dpuserOutput *hist;

class qtdpuserInput : public QLineEdit {
    Q_OBJECT
public:
    qtdpuserInput(QWidget *parent = NULL);
protected:
    bool event(QEvent *e);
    virtual void keyPressEvent(QKeyEvent *e);
    virtual void dropEvent(QDropEvent *e);
    virtual void mouseReleaseEvent(QMouseEvent *);
signals:
    void tabPressed();
    void upPressed();
    void downPressed();
    void pasteRequested();
    void pasteSelectionRequested();
public slots:
    void paste();
};	

class qtdpuser : public QWidget {
    Q_OBJECT
public:
    qtdpuser(QWidget *parent = NULL);
    ~qtdpuser();
    qtdpuserInput *input;
    QStringList *list;
    QTemporaryFile redirector;
//    std::stringstream stdout_buffer, stderr_buffer;
//    std::streambuf *oldstdout_buffer, *oldstderr_buffer;
    dpuserOutput *history;
    QStringList::const_iterator histpos;
    QLabel *prompt;
    QFitsSimplestButton *hideButton;
    void executeCommand(const QString &);
    void executeScript(const QStringList &);
    virtual void keyPressEvent(QKeyEvent *e);
    QString oldfont;
    int oldfontsize;
    void dropEvent(QDropEvent* event);
    void enableRedirector();
signals:
    void statusbartext(const QString &);
    void dpuserExited();
public slots:
    void appendHistory();
    void fileNameCompletion();
    void historyUp();
    void historyDown();
    void dpuserText(const QString &);
    void paste();
    void pasteSelection();
    void fontchanged();
    void getStdout();
protected:
    virtual void resizeEvent( QResizeEvent *e );
    virtual void enterEvent(QEvent *);
};

/* Utility function to easily request help */
void dpDisplayOutput(const QString &what);

#endif /* QTDPUSER_H */
