#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
class QLabel;
class QRadioButton;
class QSpinBox;
class QCheckBox;
class TableModel;
class QTableView;
class GraphView;
class QPushButton;
class QButtonGroup;
class QFile;
class QDoubleSpinBox;

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);

private slots:
    void open();
    void saveAs();
    void exportForWeka();
    void saveSet();
    void updateRanges();
    void updateResults();
    void setToFullRange();

private:    
    bool loadFile(const QString &fileName);
    bool writeFile(const QString &fileName) const;
    bool writeCsvWekaFile(const QString &fileName) const;
    bool writeArffWekaFile(const QString &fileName) const;

    void createMenus();
    void createInterface();
    void layoutInterface();

    QMenu *fileMenu;
    QAction *openAction;
    QAction *saveAsAction;
    QAction *exportForWekaAction;
    QAction *saveSetAction;
    QAction *quitAction;

    QButtonGroup *functionGroup;
    QRadioButton *noneRadioButton;
    QRadioButton *logRadioButton;
    QRadioButton *squareRadioButton;
    QRadioButton *powerRadioButton;
    QRadioButton *derivRadioButton;
    QRadioButton *avgRadioButton;
    QRadioButton *sumRadioButton;
    QRadioButton *minRadioButton;
    QRadioButton *maxRadioButton;
    QRadioButton *rangeRadioButton;

    QLabel *rangeLabel;
    QLabel *toLabel;
    QLabel *numOfPointsLabel;
    QLabel *subtractLabel;

    QCheckBox *groupCheckBox;
    QCheckBox *simplifyCheckBox;

    QDoubleSpinBox *powSpinBox;
    QSpinBox *derivSpinBox;
    QSpinBox *rangeSmallSpinBox;
    QSpinBox *rangeBigSpinBox;
    QSpinBox *numOfPointsSpinBox;
    QSpinBox *subtractSpinBox;

    QPushButton *fullRangeButton;

    QTabWidget *tabWidget;
    QTableView *origTableView;
    QTableView *resultTableView;
    GraphView *origGraphView;
    GraphView *resultGraphView;

    TableModel *origModel;
    TableModel *resultModel;
};

struct List2DOperations
{
    static QString getCsvHeaderString(const QStringList colTitles, bool isSwapped);
    static QString getArffHeaderString(const QStringList colTitles);
    static QString getContentsString(const QList<QList<double> > contents, const QList<QString> rowTitles, bool isSwapped);

    static QList<QList<double> > derivative(QList<QList<double> > origList, int times);
    static QList<QList<double> > logOneOverR(QList<QList<double> > origList);
    static QList<QList<double> > rSquared(QList<QList<double> > origList);
    static QList<QList<double> > rToTheN(QList<QList<double> > origList, double n);
    static QList<QList<double> > averageInInterval(QList<QList<double> > origList, int numIntervals);
    static QList<QList<double> > sumInInterval(QList<QList<double> > origList, int numIntervals);
    static QList<QList<double> > minInInterval(QList<QList<double> > origList, int numIntervals);
    static QList<QList<double> > maxInInterval(QList<QList<double> > origList, int numIntervals);
    static QList<QList<double> > rangeInInterval(QList<QList<double> > origList, int numIntervals);
    static QList<QList<double> > shrinkToNumPoints(QList<QList<double> > origList, int numPoints);
    static QList<QList<double> > shrinkToRange(QList<QList<double> > origList, int minIndex, int maxIndex);
    static QList<QList<double> > subtractList(QList<QList<double> > origList, QList<double> otherList);

    static QStringList titleDeriv(QStringList origList, int times);
    static QStringList titleShrink(QStringList origList, int numPoints);
    static QStringList titleRange(QStringList origList, int minIndex, int maxIndex);

    static QList<QList<double> > swapAxes(QList<QList<double> > origList);
};

#endif // MAINWINDOW_H
