// File ExaminerViewer.h by az

#ifndef EXAMINERVIEWER_H
#define EXAMINERVIEWER_H


#include <Inventor/Qt/viewers/SoQtExaminerViewer.h>
#include <Inventor/SoOffscreenRenderer.h>

#include <QPushButton>
#include <QObject>

#include <vector>
#include <set>

class QImage;
class QLabel;
class SoExtSelection;
class SoBaseColor;
class SoCallbackAction;
class SoPrimitiveVertex;
class SimNode;
class SimTriangle;
class SbBSPTree;
class SoCoordinate3;
class SoIndexedLineSet;
class SoPointSet;
class SoEventCallback;
class SoOffscreenRenderer;
class SoDrawStyle;
class SoMaterial;
class RTMSimulator;
class Triangle;
struct TriangleSettings;


/**
 * @brief Generates a viewer widget to display 3D models.
 *
 * This class was mainly copied from SoQt library. Minor Changes have been made,
 * for adding some additional controls to the ExaminerViewer class.
 */
class ExaminerViewer : public QObject, public SoQtExaminerViewer
{
    Q_OBJECT
private:
    int                 m_numVertices;
    QPushButton*        m_pPerspectiveButton;
    QPushButton*        m_pBackgroundColorButton;
    QPushButton*        m_pUnitStretchButton;
    QLabel*             m_pCellSizeDisplayLabel;
    SoQtThumbWheel*     m_pCellSizeWheel;
    QWidget*            m_pBaseWidget;
    SoSeparator*        m_root;
    SoSeparator*        m_absRoot;
    SoBaseColor*        m_baseColor;
    SoSeparator*        m_shapeRoot;
    SoDrawStyle*        m_shapeDrawStyle;
    SoMaterial*         m_shapeMaterial;
    SoMaterial*         m_nodeMaterial;
    SoCoordinate3*      m_shapeTriangles;
    SbPList*            m_appButtons;



    static RTMSimulator*          s_pSimulator;
    static SoExtSelection*        s_pSelection;
    static bool                   s_fViewerIsEmpty;
    static int                    s_selection_trianglecounter;
    static int                    s_selection_linecounter;
    static int                    s_selection_pointcounter;
    static SbList<int32_t>        s_myidxlist;
    static SbBSPTree              s_mybsptree;
    static SbBSPTree              s_mypointbsptree;
    static SoCoordinate3*         s_mycoords;
    static SoIndexedLineSet*      s_mylineset;
    static SoCoordinate3*         s_mypointcoords;
    static SoPointSet*            s_mypointset;
    static std::vector<SimNode*>  s_SelectedNodes;

private:
    void initSelection();
    static SoSeparator* make_line_sg(void);
    static void start_callback(void * userdata, SoSelection * sel);
    static void finish_callback(void * userdata, SoSelection * sel);
    static void made_selection( void * userdata, SoPath * path );
    static void event_cb(void * userdata, SoEventCallback * node);
    static SbBool lineCB(void * userdata, SoCallbackAction * action, const SoPrimitiveVertex * v1, const SoPrimitiveVertex * v2);
    static SbBool pointCB(void * userdata, SoCallbackAction * action, const SoPrimitiveVertex * v1);
    static SbBool triangleCB(void * userdata, SoCallbackAction * action, const SoPrimitiveVertex * v1, const SoPrimitiveVertex * v2, const SoPrimitiveVertex * v3);


public:
    ExaminerViewer(QWidget * parent, RTMSimulator* pSimulator);
    ~ExaminerViewer();
    QWidget* buildRightTrim(QWidget * parent);
    QWidget* buildLeftTrim(QWidget * parent);
    void initGraph();
    void paint_shit();
    SimNode* addNode(int id, double x, double y, double z);
    void removeNode(SimNode* node);
    SimTriangle* addTriangle(int triangleId, SimNode* node1, SimNode* node2, SimNode* node3);
    SimTriangle* addTriangle(TriangleSettings &settings);
    void clear();
    static std::vector<SimNode*> getSelection();
    static bool isViewerEmpty();
    void createSnapShot(QString strFileName = "");
    bool writeToImage (QImage& img, SoOffscreenRenderer& renderer);
    float nodeTransparency();
    void setCellSize(float v);
    void setUnitStretch(bool m);

protected:
    virtual void createViewerButtons(QWidget * parent, SbPList * buttonlist);
    virtual void createAppButtons(QWidget * parent, SbPList * buttonlist);
    virtual QPushButton * getAppbutton(const int idx);
    virtual QWidget* buildAppButtons(QWidget * parent);

public slots:
    void buttonHomeClicked();
    void buttonSelectClicked();
    void buttonSingleSelectClicked();
    void buttonDragClicked();
    void buttonSetHomeClicked();
    void buttonViewAllClicked();
    void buttonDefineBackgroundColorClicked(bool blackorwhite);
    void rightWheelPressed(void);
    void rightWheelChanged(float v);
    void rightWheelReleased(void);
    void leftWheelPressed(void);
    void leftWheelChanged(float v);
    void leftWheelReleased(void);
    void cellSizeWheelChanged(float v);


    void setPerspectiveView(bool perspective);
    void setShapeTransparency(int value);
    void setNodeTransparency(int value);
    void setMilliMeterUnit(bool mm);
    void moveCamera(float x, float y, float z);
    void rotateCamera(float val0, float val1, float val2, float val3);
#ifdef DEBUG
    void testMultipleTriangleStrips();
#endif //DEBUG
};

/**
 * @brief Functor class for stl algorithms to remove a SimNode from the graph.
 */
class RemNode
{
    ExaminerViewer* viewer;
public:
    explicit RemNode(ExaminerViewer* v) : viewer(v) {}
    void operator() (std::pair<int,SimNode*> simnode_pair) {
        viewer->removeNode(simnode_pair.second);
    }
};


#endif //EXAMINERVIEWER_H
