/*
 * QFitsView
 *
 * File: imred.h
 *
 * Purpose: definition of data reduction dialogs
 *
 */

#ifndef IMRED_H
#define IMRED_H

#include <QDialog>
#include <QLineEdit>
#include <QLabel>
#include <QPushButton>
#include <QRadioButton>
#include <QValidator>
#include <QComboBox>
#include <QSpinBox>
#include <QVBoxLayout>
#include <QButtonGroup>
#include <QTableWidget>

#include <vector>
#include <map>

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

class QFitsMainWindow;

//------------------------------------------------------------------------------
// needed for imRedUser
//------------------------------------------------------------------------------
typedef struct userfunctionstruct {
    QStringList types;
    QStringList labels;
    QStringList defaultValues;
} _userfunctionstruct;

typedef std::map<QString,userfunctionstruct> _userDialogs;
extern _userDialogs userDialogs;

//------------------------------------------------------------------------------
// abstract:
// imRedGeneric
//------------------------------------------------------------------------------
class imRedGeneric : public QDialog {
    Q_OBJECT
public:
    imRedGeneric(QFitsMainWindow *parent);
    virtual ~imRedGeneric() {}

protected:
    void    addButtons(QWidget *lastWidget,
                       bool help = true,
                       bool displayNewBuffer = true);
    QString saveConvert(const QString &);
    int     getCurrentBufferIndex();

public slots:
    void show();
    void help();
    virtual void accepted() {}

protected:
    QVBoxLayout     *mainLayout;
    QString         action;
    QLabel          *currentBufferLabel;
    QRadioButton    *newBufferButton;
};

//------------------------------------------------------------------------------
// imRedUser
//------------------------------------------------------------------------------
class imRedUser : public imRedGeneric {
    Q_OBJECT
public:
    imRedUser(QFitsMainWindow *parent);
    virtual ~imRedUser() {}

    static void showDialog(QFitsMainWindow *parent,
                           QString which);

public slots:
    void accepted();
    void show(QString which);
    void getFileName();
signals:
    void fileSelected(QString);
private:
    std::map<int, QWidget*> fields;
    std::vector<QLabel*>    labels;
};

//------------------------------------------------------------------------------
// abstract:
// imFilterGeneric
//------------------------------------------------------------------------------
class imFilterGeneric : public imRedGeneric {
    Q_OBJECT
public:
    imFilterGeneric(QFitsMainWindow *parent);
    virtual ~imFilterGeneric() {}

protected:
    QGridLayout *gridLayout;
    QSpinBox    *xsize,
                *ysize;
    QLineEdit   *centerX,
                *centerY;
};

//------------------------------------------------------------------------------
// imFilterGauss
//------------------------------------------------------------------------------
class imFilterGauss : public imFilterGeneric {
    Q_OBJECT
public:
    imFilterGauss(QFitsMainWindow *parent);
    ~imFilterGauss() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit   *fwhm1,
                *fwhm2,
                *angle;
};

//------------------------------------------------------------------------------
// imFilterEllipse
//------------------------------------------------------------------------------
class imFilterEllipse : public imFilterGeneric {
    Q_OBJECT
public:
    imFilterEllipse(QFitsMainWindow *parent);
    ~imFilterEllipse() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QSpinBox    *major,
                *minor;
    QLineEdit   *angle;
};

//------------------------------------------------------------------------------
// imFilterMoffat
//------------------------------------------------------------------------------
class imFilterMoffat : public imFilterGeneric {
    Q_OBJECT
public:
    imFilterMoffat(QFitsMainWindow *parent);
    ~imFilterMoffat() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit   *power,
                *fwhm1,
                *fwhm2,
                *angle;
};

//------------------------------------------------------------------------------
// imFilterAiry
//------------------------------------------------------------------------------
class imFilterAiry : public imRedGeneric {
    Q_OBJECT
public:
    imFilterAiry(QFitsMainWindow *parent);
    ~imFilterAiry() {}

    static void showDialog(QFitsMainWindow *parent);

protected:
    QGridLayout *gridLayout;
    QSpinBox    *xsize,
                *ysize;
public slots:
    void accepted();

private:
    QDoubleSpinBox   *diameter,
                *pixelscale,
                *wavelength;
};

//------------------------------------------------------------------------------
// imRedRotate
//------------------------------------------------------------------------------
class imRedRotate : public imRedGeneric {
    Q_OBJECT
public:
    imRedRotate(QFitsMainWindow *parent);
    ~imRedRotate() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit   *angle,
                *centerX,
                *centerY;
};

//------------------------------------------------------------------------------
// imRedShift
//------------------------------------------------------------------------------
class imRedShift : public imRedGeneric {
    Q_OBJECT
public:
    imRedShift(QFitsMainWindow *parent);
    ~imRedShift() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit       *xshift,
                    *yshift,
                    *zshift;
    QRadioButton    *wrap;
    bool            is3D;
};

//------------------------------------------------------------------------------
// imRedCrop
//------------------------------------------------------------------------------
class imRedCrop : public imRedGeneric {
    Q_OBJECT
public:
    imRedCrop(QFitsMainWindow *parent);
    ~imRedCrop() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QSpinBox    *x1, *x2,
                *y1, *y2,
                *z1, *z2;
};

//------------------------------------------------------------------------------
// imRedCblank
//------------------------------------------------------------------------------
class imRedCblank : public imRedGeneric {
    Q_OBJECT
public:
    imRedCblank(QFitsMainWindow *parent);
    ~imRedCblank() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit    *value;
};

//------------------------------------------------------------------------------
// imRedResize
//------------------------------------------------------------------------------
class imRedResize : public imRedGeneric {
    Q_OBJECT
public:
    imRedResize(QFitsMainWindow *parent);
    ~imRedResize() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QSpinBox    *resizeX,
                *resizeY,
                *resizeZ;
};

//------------------------------------------------------------------------------
// imRedRebin
//------------------------------------------------------------------------------
class imRedRebin : public imRedGeneric {
    Q_OBJECT
public:
    imRedRebin(QFitsMainWindow *parent);
    ~imRedRebin() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QSpinBox    *rebinX,
                *rebinY,
                *rebinZ;
};

//------------------------------------------------------------------------------
// imRedCreatePSF
//------------------------------------------------------------------------------
class imRedCreatePSF : public imRedGeneric {
    Q_OBJECT
public:
    imRedCreatePSF(QFitsMainWindow *parent);
    ~imRedCreatePSF() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit   *low,
                *fwhm;
    QSpinBox    *nstars,
                *cbell1,
                *cbell2;
};

//------------------------------------------------------------------------------
// imRedSmooth
//------------------------------------------------------------------------------
class imRedSmooth : public imRedGeneric {
    Q_OBJECT
public:
    imRedSmooth(QFitsMainWindow *parent);
    ~imRedSmooth() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit       *fwhm;
    QButtonGroup    *methodButtonGroup,
                    *axesButtonGroup;
    QRadioButton    *method1Button,
                    *method2Button,
                    *method3Button,
                    *xyButton,
                    *xButton,
                    *yButton,
                    *zButton;
    bool            is3D;
};

//------------------------------------------------------------------------------
// imRedSmoothSubtract
//------------------------------------------------------------------------------
class imRedSmoothSubtract : public imRedGeneric {
    Q_OBJECT
public:
    imRedSmoothSubtract(QFitsMainWindow *parent);
    ~imRedSmoothSubtract() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit       *fwhm;
    QButtonGroup    *methodButtonGroup;
    QRadioButton    *method1Button,
                    *method2Button,
                    *method3Button;
};

//------------------------------------------------------------------------------
// imRedWien
//------------------------------------------------------------------------------
class imRedWien : public imRedGeneric {
    Q_OBJECT
public:
    imRedWien(QFitsMainWindow *parent);
    ~imRedWien() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit *factor;
    QComboBox *psf;
};

//------------------------------------------------------------------------------
// imRedLucy
//------------------------------------------------------------------------------
class imRedLucy : public imRedGeneric {
    Q_OBJECT
public:
    imRedLucy(QFitsMainWindow *parent);
    ~imRedLucy() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit   *thresh;
    QSpinBox    *niter;
    QComboBox   *psf;
};

//------------------------------------------------------------------------------
// imRedVelmap
//------------------------------------------------------------------------------
class imRedVelmap : public imRedGeneric {
    Q_OBJECT
public:
    imRedVelmap(QFitsMainWindow *parent);
    ~imRedVelmap() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit       *center, *fwhm, *thresh;
    QButtonGroup    *methodButtonGroup;
    QRadioButton    *method1Button,
                    *method2Button;
};

//------------------------------------------------------------------------------
// imRedEvalVelmap
//------------------------------------------------------------------------------
class imRedEvalVelmap : public imRedGeneric {
    Q_OBJECT
private:public:
    imRedEvalVelmap(QFitsMainWindow *parent);
    ~imRedEvalVelmap() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QComboBox   *data,
                *velmap;
};

//------------------------------------------------------------------------------
// imRedCorrmap
//------------------------------------------------------------------------------
class imRedCorrmap : public imRedGeneric {
    Q_OBJECT
public:
    imRedCorrmap(QFitsMainWindow *parent);
    ~imRedCorrmap() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QComboBox   *templateSpec;
};

//------------------------------------------------------------------------------
// imRedLongslit
//------------------------------------------------------------------------------
class imRedLongslit : public imRedGeneric {
    Q_OBJECT
public:
    imRedLongslit(QFitsMainWindow *parent);
    ~imRedLongslit() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();
    void reject();
    void someValueChanged(const QString &);
    void angleChanged(double);
    void opening_angleChanged(double);
    void centerChanged(int, int);
    void zeroDegPressed();
    void ninetyDegPressed();

signals:
    void longslitChangedValues(int, int, double, int, double);

private:
    QSpinBox    *xcenter,
                *ycenter,
                *slitwidth;
    QLineEdit   *angle;
    QDoubleSpinBox  *opening_angle;
    QPushButton *zeroDeg,
                *ninetyDeg;
    QCustomPlot *plotarea;
    bool        is3D;
};

//------------------------------------------------------------------------------
// imRedEllipticalProfile
//------------------------------------------------------------------------------
class imRedEllipticalProfile : public imRedGeneric {
    Q_OBJECT
public:
    imRedEllipticalProfile(QFitsMainWindow *parent);
    ~imRedEllipticalProfile() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();
    void reject();
    void someValueChanged(const QString &);
    void angleChanged(double);
    void ratioChanged(double);
    void centerChanged(int, int);

signals:
    void ellipticalProfileChangedValues(int, int, double, double, int);

private:
    QSpinBox        *xcenter,
                    *ycenter,
                    *slitwidth;
    QDoubleSpinBox  *angle;
    QLineEdit       *ratio;
    bool            is3D;
};

//------------------------------------------------------------------------------
// imRedMarkpos
//------------------------------------------------------------------------------
class imRedMarkpos : public QWidget {
    Q_OBJECT
public:
    imRedMarkpos(QFitsMainWindow *parent);
    ~imRedMarkpos() {}

    virtual void show();
    void setRadius(int value) { radius->setValue(value); }
    void setMethod(int method);
    void clearValues();

    QMap<dpString, QVector<int> > positions;

public slots:
//    void accepted();
//    void reject();
    void newPosition(int, int);
    void updateMethod();
    void createBufferFromValues();

signals:
    void markposChangedValues(QVector<int>);

private:
    QSpinBox        *radius;
    QButtonGroup    *methodButtonGroup;
    QRadioButton    *method0Button,
                    *method1Button,
                    *method2Button,
                    *method3Button;
    QTableWidget    *positionsTable;
    QPushButton     *createButton;
};

//------------------------------------------------------------------------------
// imRedVoronoi
//------------------------------------------------------------------------------
class imRedVoronoi : public imRedGeneric {
    Q_OBJECT
public:
    imRedVoronoi(QFitsMainWindow *parent);
    ~imRedVoronoi() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit   *targetSN;
    QComboBox   *signal,
                *noise,
                *target;
};

//------------------------------------------------------------------------------
// imRedSetWCS
//------------------------------------------------------------------------------
class imRedSetWCS : public imRedGeneric {
    Q_OBJECT
public:
    imRedSetWCS(QFitsMainWindow *parent);
    ~imRedSetWCS() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QLineEdit   *crpix1, *crval1, *cdelt1,
                *crpix2, *crval2, *cdelt2,
                *crpix3, *crval3, *cdelt3;
    bool        is2D,
                is3D;
};

//------------------------------------------------------------------------------
// imRedArithImage
//------------------------------------------------------------------------------
class imRedArithImage : public imRedGeneric {
    Q_OBJECT
public:
    imRedArithImage(QFitsMainWindow *parent);
    ~imRedArithImage() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QComboBox   *oper,
                *operand;
};

//------------------------------------------------------------------------------
// imRedArithNumber
//------------------------------------------------------------------------------
class imRedArithNumber : public imRedGeneric {
    Q_OBJECT
public:
    imRedArithNumber(QFitsMainWindow *parent);
    ~imRedArithNumber() {}

    static void showDialog(QFitsMainWindow *parent);

public slots:
    void accepted();

private:
    QComboBox *oper;
    QLineEdit *operand;
};

#endif /* IMRED_H */
