#ifndef DISPLAY3D_H
#define DISPLAY3D_H

#include <qgl.h>
#include <qpen.h>
#include <vector>
#include <CompuCell3D/Field3D/Point3D.h>
#include "GraphicsData.h"
#include "GraphicsDataFields.h"
#include "GraphicsBase.h"
#include "Configure3DData.h"

#include <qsplitter.h>

class QColor;
class Projection2DData;
class GraphicsDataFields;
class UniversalGraphicsSettings;



class Display3D : public QGLWidget, public GraphicsBase
{
public:
   typedef GraphicsDataFields::field3DGraphicsData_t field3DGraphicsData_t;
   typedef GraphicsDataFields::floatField3D_t floatField3D_t;
    Display3D(QWidget *parent = 0, const char *name = 0);

   virtual void paintLattice();
   virtual void paintLegend( float minConcentration, float maxConcentration,std::string location,std::string type);
   virtual unsigned int legendDimension(std::string location, unsigned int &rectWidth,unsigned int & rectHeight,std::string type);
   virtual void paintConcentrationLattice();
   virtual void fillFakeConcentration(){};
   virtual void paintCellVectorFieldLattice();
   virtual void doContourLines(){};
   virtual void produceImage(QImage & image);
        

   float getRotationX();
   float getRotationY();
   float getRotationZ();
    
    void setSizeLMN(unsigned int _sizeL , unsigned int _sizeM ,unsigned int _sizeN);
    void setDrawingAllowedFlag(bool);
    
    Configure3DData getConfigure3DData();
    void setConfigure3DData(const Configure3DData & _data);
    void setInitialConfigure3DData(const Configure3DData & _data);
    
protected:

    void (Display3D::*drawFcnPtr)();
    //bool avoidType(unsigned short type);
    void setDimensions(GLfloat _sizeX,GLfloat _sizeY, GLfloat _sizeZ );
    void drawCube(GLfloat x, GLfloat y , GLfloat z , GLfloat side );
    void drawCube(GLfloat x, GLfloat y , GLfloat z , GLfloat side, const QColor &color );
    void drawSquare(GLfloat x, GLfloat y , GLfloat z , GLfloat side, const QColor &color);
    void drawRectangle(GLfloat x, GLfloat y , GLfloat z , GLfloat width , GLfloat height, const QColor &color);
    void initDraw();
    void prepareScene();//pushes matrix
    void prepareSceneColorMap();//pushes matrix
    void paint3DLattice();//must pop matrixv
    void paint3DConcentrationLattice();//must pop matrixv
    void paint3DCellVectorFieldLattice();//must pop matrixv
    
    void initializeGL();
    void resizeGL(int width, int height);
    
    void paintGL();
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseDoubleClickEvent(QMouseEvent *event);
    

    
    
private:
    void draw();
    int faceAtPosition(const QPoint &pos);
    bool checkIfInside(unsigned int x, unsigned y, unsigned z);
    void doBorders(unsigned int x,unsigned int y,unsigned int z );
    bool belongsToField(CompuCell3D::Point3D &pt);
    
    GLfloat rotationX;
    GLfloat rotationY;
    GLfloat rotationZ;
    QColor faceColors[6];
    QPoint lastPos;
    
    std::vector<std::vector<std::vector<GLfloat> > >   cubeCoords;
    std::vector< GLfloat >   cubeCoordsVec;
    GLfloat sizeX,sizeY,sizeZ;
    
    Configure3DData data3DConf;

    
    unsigned int sizeL,sizeM,sizeN;
    unsigned int maxDimension;

    
    field3DGraphicsData_t * field3DGraphicsDataPtr;
    
    unsigned int currentZoomFactor;
    bool drawingAllowed;
    unsigned int legendOffset;
    float enlargementFactor;
};

inline bool Display3D::belongsToField(CompuCell3D::Point3D &pt){
   if(pt.x>=0 && pt.x<sizeL && pt.y>=0 && pt.y<sizeM && pt.z>=0 && pt.z<sizeN)
      return true;
   else
      return false;
}



inline float Display3D::getRotationX(){return rotationX;}
inline float Display3D::getRotationY(){return rotationY;}
inline float Display3D::getRotationZ(){return rotationZ;}
inline void Display3D::setDrawingAllowedFlag(bool _flag){drawingAllowed=_flag;}

inline Configure3DData Display3D::getConfigure3DData(){return data3DConf;}
inline void Display3D::setConfigure3DData(const Configure3DData & _data){data3DConf=_data;}



#endif
