/*
 * 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 <QObject>
#include <QTimer>
#include <QLabel>
#include <QListWidget>
#include <QMainWindow>
#include <QPushButton>

//#include <QtOpenGL/QGLWidget>
#include "../BasicGlCamera.h"

#include <QMouseEvent>
#include <QColorDialog>
#include <QApplication>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QRadioButton>
#include <QCheckBox>
#include <iostream>
#include <GL/gl.h>

#include <qwt_plot.h>
//#include "qwt_plot_histogram.h"
#include <qwt_plot_curve.h>

#include <qwt_plot_zoomer.h>

#include <valarray>

#include <string>

namespace std
{
    class fits;
}

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

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



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

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

protected:
//    void initializeGL();
//    void resizeGL(int width, int height);
    void paintGL();
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseDoubleClickEvent(QMouseEvent *event);
    void drawCamera(bool alsoWire);
//    void drawPatches();
//    int PixelAtPosition(const QPoint &pos);
//    void drawHexagon(int index, bool solid);
    int selectedPixel;
    float *eventData;
    int16_t* rawEventData;
    int16_t* waveLetArray;

private:
    void drawPixelCurve();
//    void updateNeighbors(int currentPixel);
//    void skipPixels(int start, int howMany);
//    void calculatePixelsCoords();
    void setCorrectSlice(QMouseEvent* event);
    void eventStepping(bool plus);
//    void buildVerticesList();
    void buildPatchesIndices();
    void calcBlurColor(int pixel, int vertex);
    void drawBlurryHexagon(int index);
    int whichSlice;
 //   float shownSizex;
 //   float shownSizey;
    bool drawPatch;
    bool drawImpulse;
    bool drawBlur;
    bool loopCurrentEvent;
    //allocate the maximum size for one event
    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 nRoiTM;
    int runNumber;
    int nTM;
    int runType;
    int firstDataTime;
    int lastDataTime;
    int revision;
    int builderVersion;
    int nBoards;
    int nPixels;
    std::string timeSystem;
    std::string creationDate;
    int nightInt;
    std::string camera;
    std::string daq;
    float adcCount;
    int nbOk;
    int nbRej;
    int nbBad;

    int eventStep;

//    int hardwareMapping[1440];
//    int softwareMapping[1440];
////    int patches[160][9];
    GLfloat patchesColor[160][3];
//    vector<edge> patchesIndices[160];
    std::fits* inputFile;
    std::fits* calibInputFile;
    float baseLineMean[1440*1024];
    float gainMean[1440*1024];
    float triggerOffsetMean[1440*1024];
    bool calibrationLoaded;
    bool drawCalibrationLoaded;

    QPoint lastPos;

    void doMyWaveletTestPlease();
    void doWaveLetOnCurrentEventPlease();
    bool doWaveLetsPlease(int givenSpan, int16_t* orig, int16_t* wavelets, bool verifyResult);
public:
    void computePulsesStatistics();
    double aMeas[1024];
    double n1mean[1024];
    double n2mean[1024];
    double vCorr[1024];

//    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 loadNewCalibFileClicked();
    void fileSelected(QString file);
    void calibFileSelected(QString file);
    void drawPatchesCheckChange(int state);
    void drawImpulseCheckChange(int state);
    void drawBlurCheckChange(int state);
    void loopEventCheckChange(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);
    void pixelChanged(int pixel);
    void hwIDChanged(int hwid);
    void swIDChanged(int swid);
    void crateIDChanged(int cid);
    void boardIDChanged(int bid);
    void patchIDChanged(int pid);
    void autoScalePressed();
    void entireCameraChanged(bool state);
    void currentPixelChanged(bool state);
    void slicesPlusPlus();
    void slicesMinusMinus();
    void drawCalibratedDataChanged(int state);
    void eventChangedFromSpinner(int cEvent);
    void sliceChangedFromSpinner(int cSlice);

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


private:
    RawDataViewer* viewer;
    QTimer timer;
    std::string currentFile;
    std::string currentCalibFile;
    int crateID;
    int boardID;
    int patchID;
    int hwID;
    int swID;
    bool rescaleWholeCamera;
    QRectF scaleBoundingRectangle(QRectF rectangle, float scale);
    bool updateSpinnerDisplay;

public:
    QListWidget *boardsTimeList;
    QListWidget* startPixelsList;
    QListWidget* startTimeMarksList;
//   QLabel*      fileLoadedLabel;
//    QLabel*      runNumberLabel;
//    QLabel*      numberOfSlicesLabel;
//    QLabel*      numberOfTimeMarksLabel;
//    QLabel*      runTypeLabel;
//    QLabel*      firstTimeLabel;
//    QLabel*      lastTimeLabel;
    QLabel*      currentPixelValue;
    QLabel*      extraInfoLabel;

    QwtPlot*     boardsTimeHisto;
    QwtPlot*     startCellHisto;
    QwtPlot*     startTimeMarkHisto;
    QwtPlot*     pixelValueCurve;
    QwtPlotCurve boardsTimeHistoItem;
    QwtPlotCurve startCellHistoItem;
    QwtPlotCurve startTimeMarkHistoItem;
    QwtPlotCurve     pixelValueCurveItem;
    QwtPlotCurve     aMeanCurveItem;
    QwtPlotCurve     vCorrCurveItem;
    QwtPlotCurve     meanCurveItem;
    QwtPlotZoomer* curveZoom;
    QwtPlotZoomer* boardsTimeHistoZoom;
    QwtPlotZoomer* startCellHistoZoom;
    QwtPlotZoomer* startTimeMarkHistoZoom;

    QwtPlot*        triggerDelayHisto;
    QwtPlotCurve triggerDelayHistoItem;
    QwtPlotZoomer* triggerDelayHistoZoom;

    QPushButton* autoScaleColor;

    QListWidget* triggerDelayList;

    QSpinBox*   HwIDBox;
    QSpinBox*   SwIDBox;
    QSpinBox*   crateIDBox;
    QSpinBox*   boardIDBox;
    QSpinBox*   patchIDBox;

    QSpinBox*   eventNumberBox;

    QRadioButton* currentPixelScale;
    QRadioButton* entireCameraScale;
    QRadioButton* playEventsRadio;

    QDoubleSpinBox* range0;
    QDoubleSpinBox* range1;
    QDoubleSpinBox* range2;
    QDoubleSpinBox* range3;
    QDoubleSpinBox* range4;

    QCheckBox*  drawCalibrationCheckBox;

    void initHistograms();

};

#endif /* QTGL_H_ */
