#ifndef QFITSWIDGETTABLE_H
#define QFITSWIDGETTABLE_H

#include <QTableView>
#include <QAbstractTableModel>
#include <QComboBox>
#include <QWidget>
#include <QList>
#include <QHBoxLayout>
#include <QPair>

#include "QFitsBaseWidget.h"
#include "QFitsMultiBuffer.h"

class QStandardItemModel;
class QFitsMainView;
class QFitsTableModel;
class QFitsTableView;
class QFitsDummyMarkedView;
class Fits;
class dpuserType;
class dpuserTypeList;

// //////////////////////////////////////////////////////////////////////////
// class QFitsWidgetTable
// //////////////////////////////////////////////////////////////////////////
class QFitsWidgetTable : public QFitsBaseWidget {
    Q_OBJECT
//----- Functions -----
public:
    QFitsWidgetTable(QFitsBaseBuffer*);
    ~QFitsWidgetTable();
    void init(dpuserType *);

    void resizeColumns();
    QFitsSingleBuffer* getSBunderMouse(int);
    void activateSBunderMouse(int);
    void restoreState();
    void getVisibleRangeVertical(int*, int*);
    void getVisibleRangeHorizontal(int*, int*);
    void setBruteRange(int, int);

    QFitsTableModel*  getTableModel()   const { return tableModel; }
    QFitsTableView*   getTableView()    const { return tableView; }
    QFitsBaseBuffer*  getBaseBuffer()   const { return myBaseBuffer; }

    //
    // overloaded abstract base functions
    //
    void setXRange(const double &, const double &);
    QFitsBaseView* getView();

    virtual void copyImage(int);

protected:
    virtual void resizeEvent(QResizeEvent *);

//----- Slots -----
//----- Signals -----
//----- Members -----
private:
    QFitsTableView    *tableView;
    QFitsTableModel   *tableModel;
    QFitsBaseBuffer   *myBaseBuffer;
    QFitsDummyMarkedView *dummyView;
};

// //////////////////////////////////////////////////////////////////////////
// class QFitsTableModel
// //////////////////////////////////////////////////////////////////////////
class QFitsTableModel : public QAbstractTableModel {
    Q_OBJECT
//----- Functions -----
public:
    QFitsTableModel(QObject *parent = 0, QFitsWidgetTable *table = 0);
    virtual void setDpData(dpuserType*);
    virtual QString newBufferString(int, int, int, int);
    virtual Fits* createPlotData(int, QFV::Orientation);
    virtual int translateColumnNumber(int *section) const { return -1; }
    virtual int rowCount(int) const;
    virtual int columnCount(int) const;
    virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;

    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
protected:
    Fits* extractPlotData(dpuserType*, int, QFV::Orientation);
    double isZero(double) const;
    QVariant dataFromDpuserType(dpuserType*, int, int) const;

private:
    virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
    virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
    virtual Qt::ItemFlags flags(const QModelIndex &index) const;

//----- Slots -----
//----- Signals -----
//----- Members -----
protected:
    QFitsWidgetTable *myParent;
    dpuserType       *modelDpuserType;
};

// //////////////////////////////////////////////////////////////////////////
// class QFitsTableModelMulti
// //////////////////////////////////////////////////////////////////////////
class QFitsTableModelMulti : public QFitsTableModel {
    Q_OBJECT
//----- Functions -----
public:
    QFitsTableModelMulti(QObject *parent = 0, QFitsWidgetTable *p = 0);
    virtual QString newBufferString(int, int, int, int);
    virtual Fits* createPlotData(int, QFV::Orientation);
    virtual int rowCount(int section) const;
    virtual int translateColumnNumber(int *section) const;
    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;

private:
    virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
    virtual int rCount(const dpuserType *dpt) const;
    virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
    virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    virtual Qt::ItemFlags flags(const QModelIndex &index) const;

//----- Slots -----
//----- Signals -----
//----- Members -----
};

// //////////////////////////////////////////////////////////////////////////
// class QFitsTableView
// //////////////////////////////////////////////////////////////////////////
class QFitsTableView : public QTableView {
    Q_OBJECT
public:
    QFitsTableView(QFitsWidgetTable *parent = 0);
    ~QFitsTableView();
    bool doPlotData();
    void restoreState();
    void calcScrollContinuum();
    bool getMarkedTable() { return markedTable; }
    void setMarkedTable(bool b) { markedTable = b; }
    void setBruteRange(int, int);
    void copySelectionToClipboard();
protected:
    void mousePressEvent(QMouseEvent*);
    void mouseMoveEvent(QMouseEvent*);
    void wheelEvent(QWheelEvent*);
    void handleMouseEventCaption(int);
    void handleMouseEventData();
    void keyPressEvent(QKeyEvent *);
    void enterEvent(QEvent*);
    void leaveEvent(QEvent*);
    void leaveCells();

private:
    void unsetSpectrum();
    void plotSpectrumVertical();
    void plotSpectrumHorizontal();

public slots:
    void unsetSpectrum(const QItemSelection &, const QItemSelection &);

private slots:
    void unsetSpectrum(const QModelIndex &);
    void copyWholeTableToNewBuffer();
    void copySubTableToNewBuffer();
    void copySelectionToNewBuffer();
    void setSpectrumVertical(int);
    void setSpectrumHorizontal(int);
    void setupCubeSpectrum();
    void scrollMoved(int);

private:
    QMenu                   *rightPopupMenu;
    QFitsWidgetTable        *myParent;
    Fits                    *plotSpectrum;
    int                     columnState,
                            rowState,
                            actualCellX,
                            actualCellY;
    bool                    markedTable;
    QPair<int,int>          brute_rangeHorizontal,
                            brute_rangeVertical;
};

// //////////////////////////////////////////////////////////////////////////
// class QFitsDummyMarkedView
// //////////////////////////////////////////////////////////////////////////
class QFitsDummyMarkedView : public QFitsBaseView {
    Q_OBJECT
//----- Functions -----
public:
    QFitsDummyMarkedView(QFitsWidgetTable *parent, QWidget *w = NULL);
    virtual ~QFitsDummyMarkedView() {}

    virtual void switchBackgroundColor();

    //----- Slots -----
    //----- Signals -----
    //----- Members -----
private:
    QFitsWidgetTable *myWidget;
};

#endif // QFITSWIDGETTABLE_H
