#ifndef INCOMPLETEVRMLVIEWER_H
#define INCOMPLETEVRMLVIEWER_H

#include <gtk/gtk.h>

#include "Utility.h"
#include "Toolkit.h"
#include "Trackball.h"
#include "ToolkitGtk.h"
#include "FramesPerSecond.h"
#include "GlActionVisitor.h"


typedef enum
{
	VISIBLE_COLUMN,
	NAME_COLUMN,
	NODE_POINTER,
	N_COLUMNS
} sceneGraphColumns;


enum
{
	SHADING_MODEL_FLAT,
	SHADING_MODEL_SMOOTH
};


class IncompleteVRMLViewer : public nsToolkit::ToolkitGtk
{
	private:
		nsUtility::StopWatch normalCalculation;
		nsUtility::StopWatch loading;

		nsSceneGraph::GlActionVisitor actionVisitor;

		unsigned int numberOfVertices;
		unsigned int getNumberOfVertices(nsSceneGraph::GraphNode *node = NULL);
		unsigned int numberOfTriangles;
		unsigned int getNumberOfTriangles(nsSceneGraph::GraphNode *node = NULL);

		bool useFrictionlessTrackball;
		nsToolkit::Trackball trackball;

		bool showFramesPerSecond;
		nsToolkit::FramesPerSecond framesPerSecond;

		// Font
		PangoFont *font;
		int fontHeight;
		int fontWidth;
		GLuint fontListBase;

		GtkWidget *openDialog;

		GtkWidget *popup;
		GtkItemFactory *popupItemFactory;
		GtkItemFactory *menuItemFactory;

		int defaultMaterial;

		GtkWidget *sceneGraphView;
		GtkTreeStore *sceneGraphModel;
		GtkCellRenderer *sceneGraphTextRenderer;
		GtkCellRenderer *sceneGraphPixbufRenderer;
		void sceneGraphBuild(nsSceneGraph::GraphNode *node, GtkTreeIter *parent = NULL);
		gboolean sceneGraphGetSelectedIter(GtkTreeIter *iter);
		nsSceneGraph::GraphNode *sceneGraphGetSelectedNode(void);

	public:
		IncompleteVRMLViewer(int argc, char *argv[]);
		~IncompleteVRMLViewer(void);

		void performInit(void);
		void eventRealize(void);
		void eventUnrealize(void);

		gboolean eventConfigure(GdkEvent *event);
		gboolean eventMap(GdkEvent *event);
		gboolean eventUnmap(GdkEvent *event);
		gboolean eventVisibilityNotify(GdkEvent *event);
		gboolean eventExpose(GdkEvent *event);

		gboolean eventKeyPress(GdkEvent *event);
		gboolean eventMotionNotify(GdkEvent *event);
		gboolean eventButtonPress(GdkEvent *event);
		gboolean eventButtonRelease(GdkEvent *event);

		void eventIdle(void);

		// Hint: "thiz" cause "this" is a keyword. Same as "klass" and "class".
		static void menuFileOpen(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);
		static void menuFileOpenOk(GtkWidget *widget, IncompleteVRMLViewer *thiz);
		static void menuViewReset(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);
		static void menuViewSetWireframe(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);
		static void menuViewSetFrictionless(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);
		static void menuViewSetBackfaceCulling(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);
		static void menuViewFramesPerSecond(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);
		static void menuViewShadingModel(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);
		static void menuViewModelInfo(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);
		static void menuHelpAbout(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);
		static void menuHelpOpenGLInfo(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);

		static gboolean popupHandler(IncompleteVRMLViewer *thiz, GdkEventButton *event);
		static void popupHide(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);
		static void popupUnhide(IncompleteVRMLViewer *thiz, guint action, GtkWidget *widget);

		bool isShadingModelFlat(void);
		bool isShadingModelSmooth(void);

		void setFrictionless(bool state);
};

#endif
