/*
 * QtGl.h
 *
 *  Created on: Jul 20, 2011
 *      Author: lyard
 */

#ifndef QTGL_H_
#define QTGL_H_

#define NBOARDS      40      // max. number of boards
#define NPIX       1440      // max. number of pixels
#define NTMARK      160      // max. number of timeMarker signals

//#define LOAD_RAW

#include <QtCore/QObject>
#include <QtCore/QTimer>
#include <QtGui/QLabel>
#include <QtGui/QListWidget>
#include <QtGui/QMainWindow>
#include <QtOpenGL/QGLWidget>
#include <QtGui/QMouseEvent>
#include <QtGui/QColorDialog>
#include <QtGui/QApplication>
#include <iostream>
#include <GL/gl.h>

//#define __MARS__
//#include "MFits.h"
#include <string>
#include "fits.h"

using namespace std;

#define NUM_STORED_EVENTS 5
#define MAX_NUM_PIXELS 1600
#define ACTUAL_NUM_PIXELS 1440

///structure for storing edges of hexagons (for blurry display)
struct edge
{
    int first;
    int second;
};

///structure for storing neighbors of pixels. For camera position calculation and blurry display
struct PixelsNeighbors
{
    //neighbors. clockwise, starting from top
    int neighbors[6];
    PixelsNeighbors()
    {
        for (int i=0;i<6;i++)
            neighbors[i] = -1;
    }
    int& operator[](int index){return neighbors[index];}
};

/*************************************************
 * Class Raw Data Viewer. FACT raw data diplayer
 *************************************************/
class RawDataViewer : public QGLWidget
{
    Q_OBJECT

    friend class UIConnector;
public:
    RawDataViewer(QWidget *parent = 0);
    ~RawDataViewer();
    void openFile(string& filename);

public Q_SLOTS:
    void plusEvent();
    void minusEvent();
    void setEventStep(int step);
    void nextSlice();

Q_SIGNALS:
    void signalCurrentEvent(int event);
    void signalCurrentSlice(int slice);
    void newFileLoaded();

protected:
    void initializeGL();
    void resizeGL(int width, int height);
    void paintGL();
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseDoubleClickEvent(QMouseEvent *event);

private:
    void drawCamera(bool alsoWire);
    void drawPixelCurve();
    void drawPatches();
    int PixelAtPosition(const QPoint &pos);
    void updateNeighbors(int currentPixel);
    void skipPixels(int start, int howMany);
    void calculatePixelsCoords();
    void drawHexagon(int index, bool solid);
    void setCorrectSlice(QMouseEvent* event);
    void eventStepping(bool plus);
    void buildVerticesList();
    void buildPatchesIndices();
    void calcBlurColor(int pixel, int vertex);
    void drawBlurryHexagon(int index);
    float hexRadius;
    float hexTolerance;
    float viewSize;
    int whichSlice;
    int selectedPixel;
    float pixelSize;
    float shownSizex;
    float shownSizey;
    bool drawPatch;
    bool drawImpulse;
    bool drawBlur;
    //allocate the maximum size for one event
    int16_t *eventData;
    uint32_t boardTime[NBOARDS];
    int16_t startPix[NPIX];
    int16_t startTM[NTMARK];
    uint32_t pcTime;
    uint32_t softTrig;
    uint16_t triggerType;
    int nRows;
    int rowNum;
    int eventNum;
    int nRoi;
    int runNumber;
    int nTM;
    int runType;
    int firstDataTime;
    int lastDataTime;
    int eventStep;

    int hardwareMapping[1440];
    int patches[160][9];
    GLfloat patchesColor[160][3];
    vector<edge> patchesIndices[160];
    fits* inputFile;

    QPoint lastPos;

    GLfloat pixelsCoords[MAX_NUM_PIXELS][3];
    PixelsNeighbors neighbors[MAX_NUM_PIXELS];
    GLfloat pixelsColor[ACTUAL_NUM_PIXELS][3];
    GLfloat verticesList[ACTUAL_NUM_PIXELS*6][2];
    int verticesIndices[ACTUAL_NUM_PIXELS][6];
    int numVertices;
};
/*************************************************
 * Class UIConnector. used to connect the interface to the raw data displayer
 *************************************************/
class UIConnector : public QObject
{
    Q_OBJECT
public:
    UIConnector(QWidget *parent = 0);
    void setViewer(RawDataViewer* v);

public Q_SLOTS:
    void loadNewFileClicked();
    void fileSelected(QString file);
    void drawPatchesCheckChange(int state);
    void drawImpulseCheckChange(int state);
    void drawBlurCheckChange(int state);
    void newFileLoaded();
    void playPauseClicked();
    void slicesPerSecondChanged(double value);
    void nextSlicePlease();
    void currentSliceHasChanged(int slice);
    void currentEventHasChanged(int event);
    void rangeChanged0(double value);
    void rangeChanged1(double value);
    void rangeChanged2(double value);
    void rangeChanged3(double value);
    void rangeChanged4(double value);
    void redChanged0(double value);
    void redChanged1(double value);
    void redChanged2(double value);
    void redChanged3(double value);
    void redChanged4(double value);
    void greenChanged0(double value);
    void greenChanged1(double value);
    void greenChanged2(double value);
    void greenChanged3(double value);
    void greenChanged4(double value);
    void blueChanged0(double value);
    void blueChanged1(double value);
    void blueChanged2(double value);
    void blueChanged3(double value);
    void blueChanged4(double value);

Q_SIGNALS:
    void updateCurrentSliceDisplay(QString);
    void updateCurrentEventDisplay(QString);
    void updateCurrentPCTime(QString);
    void updateCurrentSoftTrigger(QString);
    void updateCurrentTriggerType(QString);


private:
    RawDataViewer* viewer;
    QTimer timer;
    string currentFile;
public:
    QListWidget *boardsTimeList;
    QListWidget* startPixelsList;
    QListWidget* startTimeMarksList;
    QLabel*      fileLoadedLabel;
    QLabel*      runNumberLabel;
    QLabel*      numberOfSlicesLabel;
    QLabel*      numberOfTimeMarksLabel;
    QLabel*      runTypeLabel;
    QLabel*      firstTimeLabel;
    QLabel*      lastTimeLabel;

};

#endif /* QTGL_H_ */
