/*
 * Dialogs for QFitsView which are extensions to UI dialogs
 * or completely standalone
 */

#ifndef DIALOGS_H
#define DIALOGS_H

#include <QVariant>
#include <QRadioButton>
#include <QCheckBox>
#include <QGroupBox>
#include <QLabel>
#include <QSlider>
#include <QSpinBox>
#include <QCheckBox>
#include <QLineEdit>
#include <QLayout>
#include <QToolTip>
#include <QWhatsThis>
#include <QImage>
#include <QPixmap>
#include <QListWidget>
#include <QTextEdit>
#include <QTextBrowser>
//#include <QHttp>
#include <QBuffer>
#include <QPushButton>
#include <QProgressBar>
#include <QFileDialog>
#include <QSyntaxHighlighter>
#include <QButtonGroup>
#include <QComboBox>
#include <QScrollArea>
#include <QTabWidget>

#include "guitools.h"
#include "QCustomPlot/qcustomplot.h"

#ifdef HAS_PLPLOT
#include <plplot/qt.h>
#endif /* HAS_PLPLOT */

#include "QFitsGlobal.h"
#include "highlighter.h"
#include "RGBDialog.h"

QString getSaveImageFilename(QString *selectedFilter);

void alignLabels(QLabel *label1, QLabel *label2 = NULL, QLabel *label3 = NULL);

class QFitsBaseBuffer;
class QFitsHeaderViewExt;

class About : public QDialog {
    Q_OBJECT
//----- Functions -----
public:
    About(QWidget *parent = 0);
    ~About() {}

//----- Slots -----
//----- Signals -----
//----- Members -----
public:
    QFitsSimplestButton *PixmapLabel;
    QLabel *TextLabel1,
           *TextLabel2;
    QPushButton* OKButton;
};

class DpHelp : public QDialog {
    Q_OBJECT
public:
    DpHelp(QWidget *parent = 0);
    ~DpHelp() {}

    QTextBrowser *leftPanel, *mainText;
    QLineEdit *searchPanel;
    QPushButton *searchButton, *backButton;
    QString HtmlStart;
    QString currentPage, previousPage;
protected:
    void resizeEvent(QResizeEvent *);
public slots:
    void setMainUrl(const QUrl &);
    void findDocu();
    void backClicked();
};

//class checkForUpdates : public QDialog {
//    Q_OBJECT
////----- Functions -----
//public:
//    checkForUpdates(QWidget *parent = 0);
//    ~checkForUpdates();

//    void checkUpdate(void);

////----- Slots -----
//public slots:
//    void linkClicked();
//    void httpRequestFinished(int requestId, bool error);
//    void readResponseHeader(const QHttpResponseHeader &responseHeader);

////----- Signals -----
////----- Members -----
//public:
//    QHttp *http;
//    int httpGetId;
//    bool httpRequestAborted;
//    QBuffer *buffer;
//    QLabel *label;
//    QPushButton *button, *link;
//    QProgressBar *progress;
//};

class moreColourmaps : public QDialog {
    Q_OBJECT
//----- Functions -----
public:
	moreColourmaps(QWidget *parent);
    ~moreColourmaps() {}

//----- Slots -----
//----- Signals -----
signals:
	void colourmapSelected(int);

//----- Members -----
};

class CubeDisplayDialog : public QDialog {
    Q_OBJECT
//----- Functions -----
public:
    CubeDisplayDialog(QFitsMainWindow *parent);
    ~CubeDisplayDialog() {}

    int getLinemapCenterValue();
    int getLinemapWidthValue();
    int getLinemapCont1Value();
    int getLinemapCont2Value();
    int getLinemapWidth1Value();
    int getLinemapWidth2Value();

    bool getButtonDisplaySingleChecked();
    bool getButtonDisplayAverageChecked();
    bool getButtonDisplayMedianChecked();
    bool getButtonDisplayLinemapChecked();
    bool getCheckLinemapDoCont1Checked();
    bool getCheckLinemapDoCont2Checked();

    void setLinemapCenterMaxValue(int);
    void setLinemapCont1MaxValue(int);
    void setLinemapCont2MaxValue(int);
    void setLinemapSliderWavelength(int);
    void setLinemapCenterValue(int);
    void setLinemapWavelengthSliderInformation(QString*, QString*, QString*);
    void setCubeDisplayOptions(double cr, double cd, double cv, int na);

private:
    QFitsBaseBuffer* getCurrentBuffer();

//----- Slots -----
public slots:
    void show();

    void setLinemapCenterC(const QString &);
    void setLinemapCenterW(int);
    void setLinemapWidthC(const QString &);
    void setLinemapWidthW(int);
    void setLinemapCont1C(const QString &);
    void setLinemapCont1W(int);
    void setLinemapWidth1C(const QString &);
    void setLinemapWidth1W(int);
    void setLinemapCont2C(const QString &);
    void setLinemapCont2W(int);
    void setLinemapWidth2C(const QString &);
    void setLinemapWidth2W(int);
    void setDisplayMode(dpCubeMode);

//----- Signals -----
//----- Members -----
private:
    QFitsMainWindow *myParent;
    double  crpix,
            cdelt,
            crval;
    int     n3;
    bool    interactiveUpdates;

    // Cube display
    QRadioButton    *buttonDisplayMedian,
                    *buttonDisplayAverage,
                    *buttonDisplayLinemap,
                    *buttonDisplaySingle;

    // Cube movie
    QSpinBox        *spinMovieSpeed;
    QCheckBox       *checkAutoScale;

    // channels & wavelengths
    QSpinBox        *spinLinemapCenter,
                    *spinLinemapWidth,
                    *spinLinemapCont1,
                    *spinLinemapWidth1,
                    *spinLinemapCont2,
                    *spinLinemapWidth2;

    QLineEdit       *lineeditLinemapCenterW,
                    *lineeditLinemapWidthW,
                    *lineeditLinemapCont1W,
                    *lineeditLinemapWidth1W,
                    *lineeditLinemapCont2W,
                    *lineeditLinemapWidth2W;

    QCheckBox       *checkLinemapDoCont1,
                    *checkLinemapDoCont2;

    QSlider         *sliderWavelength;
    QLabel          *labelLinemapInfo,
                    *labelWavelengthSliderLabel1,
                    *labelWavelengthSliderLabel2;

    QPushButton     *buttonOk;
};

class ImageDisplay : public QDialog {
    Q_OBJECT
//----- Functions -----
public:
    ImageDisplay(QWidget* parent);
    ~ImageDisplay();

//----- Slots -----
//----- Signals -----
//----- Members -----extensionLayout
public:
    QSlider     *sliderBrightness,
                *sliderContrast;
    QSpinBox    *spinboxContrast,
                *spinboxBrightness;
    QCheckBox   *checkboxIgnoreValue;
    QLineEdit   *lineeditIgnoreValue;
    QPushButton *buttonClose;
};

class BlinkDialog : public QDialog {
    Q_OBJECT
public:
    BlinkDialog(QWidget *parent);
    ~BlinkDialog() {}

public slots:
    void deselectAll();
    void selectAll();

public:
    QListWidget *list;
    QSpinBox *timeout;
    QPushButton *cancelButton, *okButton;
};

class PlotOptionsDialog : public QDialog {
    Q_OBJECT
//----- Functions -----
public:
    PlotOptionsDialog(QWidget *parent);
    ~PlotOptionsDialog() {}

//----- Slots -----
//----- Signals -----
//----- Members -----
public:
    QComboBox *CutsStyle;
    QSpinBox *CutsWidth;
    QCheckBox *PlotTakeLimits;
    QPushButton *closeButton;
};

class dpImportDialog : public QDialog {
    Q_OBJECT
public:
    dpImportDialog(QWidget *parent, const QString &fname);
    ~dpImportDialog() {}

    QString filename;
    QRadioButton *importText, *importNumber;
    QPushButton *cancelButton, *okButton;
    QSpinBox *columns, *skiplines;
    QComboBox *delimiter;
    QCheckBox *useComment;
    QLineEdit *comment;
    QTextEdit *preview;
    PreviewHighlighter *highlighter;

public slots:
    void updatePreview(void);
    void updatePreview2(const QString &);
    void updatePreview3(int);
};

class dpPushButton : public QPushButton {
    Q_OBJECT
public:
    dpPushButton(const QString &text, QWidget *parent, int row, int col, int maxWidth = -1);
    int c, r;

public slots:
    void wasclicked();

signals:
    void dpPushButtonClicked(int &, int &);
};

class dpFitsExtensionDialog : public QDialog {
	Q_OBJECT
public:
    dpFitsExtensionDialog(QWidget *parent, const QString &fname, bool newBuffer, bool fromCmdLine = false);
    ~dpFitsExtensionDialog();

protected:
    void resizeEvent(QResizeEvent*);

private slots:
	void updateExtensionNumber(const int &);
	void updateColumnNumber(const int &);
    void extensionButtonClicked(int &, int&);
    void headerButtonClicked(int&, int&);
    void readAllExtensionsClicked();
    void rejectDialog();
    void closeDialog();
    void exitClicked();

private:
    bool                isNewBuffer;
    int                 extension,
                        column;
    QString             filename;
    QPushButton         *cancelButton,
                        *okButton,
                        *exitButton;
    QFitsHeaderViewExt  *headerView;
    QLabel              *tlabel;
    QScrollArea         *scrollareaMain,
                        *scrollareaColumn;
    QWidget             *mainWidget;
    QFrame              *columnFrame,
                        *extensionFrame;
};

class dpMpfitParameterWidget : public QWidget {
    Q_OBJECT
public:
    dpMpfitParameterWidget(QString, QWidget *);
    QString parameterName;
    QLabel *la;
    dpFitEstimate *estimate;
//    dpDoubleEdit *estimate;
//    QRadioButton *unconstrained, *constrained, *fixed;
//    dpDoubleEdit *upperBound, *lowerBound;
    dpFitResult *fitresult;
//    QLabel *result, *resulterr;
};

class dpMpfitPopupWidget : public QWidget {
    Q_OBJECT
public:
    dpMpfitPopupWidget(QWidget *);
protected:
    void resizeEvent(QResizeEvent*);
public:
    QTextEdit *fitfunction;
    QPushButton *configureMpfit, *getVariables, *dofit, *saveParams, *loadParams;
    QWidget *parametersWidget;
    QVector<QString> parameterNames;
    QMap<QString, dpMpfitParameterWidget *> parameters;
    QCheckBox *constrainX;
    dpDoubleEdit *minx, *maxx;
    QLabel *fitresult;
    QPushButton *copyButton;
public slots:
    void setParameters(void);
    void parameterChanged(double);
private:
    int leftWidth;
signals:
    void somethingChanged();
};

class dpMpfitDataSelectWidget : public QWidget {
    Q_OBJECT
public:
    dpMpfitDataSelectWidget(QString, QWidget *);
    void enableSelectors(bool);
public:
    dpPopup *data;
    QRadioButton *row, *column;
    QSpinBox *roworcolumn;

signals:
    void somethingChanged();
};

class dpMpfitConfiguration : public QDialog {
    Q_OBJECT
public:
    dpMpfitConfiguration(QWidget *parent);

    dpDoubleEdit *ftol, *xtol, *gtol, *epsfcn, *stepfactor, *covtol;
    QSpinBox *maxiter, *maxfev;
//    QCheckBox *douserscale, *nofinitecheck;
    QVBoxLayout     *mainLayout;

public slots:
    void accepted();
    void showHelp();
};

class dpMpfitDialog : public QDialog {
    Q_OBJECT
public:
    dpMpfitDialog(QWidget*);
    dpMpfitDataSelectWidget *x, *y, *xerr, *yerr;
protected:
    void resizeEvent(QResizeEvent*);
    int getBufferData(dpMpfitDataSelectWidget &which, QVector<double> &data);
    void evaluateFitFunction(Fits *parameters = NULL);
private:
    QCustomPlot *plotarea;
    QWidget *rightwidget;
    double crval, crpix, cdelt;
    bool logaxis;
    dpMpfitPopupWidget *mpfitParameters;
    dpMpfitConfiguration *mpfitConfiguration;
    QVector<double> xd, yd, yerrd, xerrd;
    bool hasNAN;
    void removeBlanks();
    QMenu           *rightPopupMenu;
    QAction *plotStyleLinesAct, *plotStyleCrossAct;
    QCPGraph::LineStyle lineStyle;
    QCPScatterStyle::ScatterShape scatterStyle;
public slots:
    void somethingChanged();
    void fitfunctionChanged();
    void fittextChanged();
    void fitestimateChanged();
    void dofit();
    void saveParams();
    void loadParams();
    void copyfit();
    void mouseClicked(QMouseEvent *);
    void setPlotStyleLines();
    void setPlotStyleCross();
};

class dpWatchdirDialog : public QDialog {
    Q_OBJECT
public:
    dpWatchdirDialog(QWidget *);
private:
    QLineEdit *path, *filter, *command;
    QPushButton *pathButton;
    QCheckBox *sleepButton;
    QSpinBox *sleepSeconds;
public slots:
    void accepted();
    void pathButtonClicked();
    void updateandshow();
    void helpClicked();
};

#ifdef HAS_PLOTTING

class QtCategoryButton : public QPushButton
{
    Q_OBJECT
public:
    QtCategoryButton(const QString& a_Text, QWidget *a_pParent, QWidget *a_pItem);

private slots:
    void ButtonPressed();

private:
    QWidget* m_pItem;
};

class dpDataSelectWidget : public QWidget {
    Q_OBJECT
public:
    dpDataSelectWidget(QString, QWidget *);
public:
    dpPopup *data;
    QLineEdit *range;
    QLabel *rangeLabel, *rangeExample;
    QSpinBox *x, *y, *z;
    int naxis, n1, n2, n3;
    bool selectedRange(int *xv, int *yv, int *zv);
signals:
    void somethingChanged();

public slots:
    void dataSelected();
    void updateRange();
};

class dpPlotConfiguration : public QWidget {
    Q_OBJECT
public:
    dpPlotConfiguration(QWidget *parent);
    QStringList plotCommands();
    void executeCommands(QCustomPlot *);
    QDoubleSpinBox *aspect;
    QDoubleSpinBox *xmin, *xmax, *ymin, *ymax;
    QCheckBox *xauto, *yauto;
    QLineEdit *title, *xtitle, *ytitle;
    QFontComboBox *titleFont;
signals:
    void somethingChanged();
};

class dpLinePlotDialog : public QWidget {
    Q_OBJECT
public:
    dpLinePlotDialog(QString title, QWidget *parent);
    QStringList plotCommands();
    Fits *xdata, *ydata, *xerrdata, *yerrdata;
    void executeCommands(QCustomPlot *);
    void addBufferData(QString, int = -1, int = -1);
private:
    dpDataSelectWidget *x, *y, *xerr, *yerr;
    QLineEdit *series;
    QComboBox *linestyle, *symbolstyle;
    QDoubleSpinBox *linewidth, *symbolwidth, *symbolsize;
    QPushButton *linecolorButton, *symbolcolorButton;
    QColor linecolor, symbolcolor;
public slots:
    void xchanged();
    void ychanged();
    void yerrchanged();
    void linecolorClicked();
    void symbolcolorClicked();
//    void xerrchanged();
//    void yerrchanged();
signals:
    void somethingChanged();
};

class dpPlplotWindow : public QMainWindow {
    Q_OBJECT
public:
    dpPlplotWindow(QWidget *);
    ~dpPlplotWindow();
//@    PLINT       strm;
    QCustomPlot *plot;
    QCPTextElement *plotTitle;
private:
//@    QtExtWidget *plot;
    QWidget *layoutWidget;
    dpPlotConfiguration *config;
    dpStringList plotCommands;
    std::vector<dpLinePlotDialog *>plots;
    QGridLayout *configlayout;
    QScrollArea *rightWidget;
protected:
    void resizeEvent(QResizeEvent*);
public slots:
    void dataChanged();
    void add();
    void addBufferData(QString, int, int);
    void copy();
    void saveAs();
    void replot();
    void generatePlplotCommands();
    void setAspectRatio(double);
    void setTitleFont(QFont);
};

#endif /* HAS_PLOTTING */


#ifdef HAS_PLPLOT
class dpPg2PlplotWindow : public QMainWindow {
    Q_OBJECT
public:
    dpPg2PlplotWindow(int pgid);
    ~dpPg2PlplotWindow();
    PLINT       strm;
    void addPlotCommand(std::string);
    void replot();
private:
    QtExtWidget *plot;
protected:
    void resizeEvent(QResizeEvent*);
public slots:
    void copy();
    void saveAs();
};
#endif /* HAS_PLPLOT */

#endif /* DIALOGS_H */
