#ifndef DEF_TX_GRAPHWINDOW
 #define DEF_TX_GRAPHWINDOW

//------------------------------------------//
//			   TKA4 CGraphWin				//
//				03. 07. 2007				//
//------------------------------------------//


//--- Includes
#include <windows.h>
#include <stdio.h>

#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>

#include "TX_Engine.h"
//=== Includes 


//--- Defines
#define DEFAULT_TITLE  "tx"

#define BEGIN_X 0
#define BEGIN_Y 0
#define BEGIN_W 640
#define BEGIN_H 480


#define USING_GLUT  true
//=== Defines


//--- Classes
class txGraphWindow;
//=== Classes 

//--- Vars
txGraphWindow  *GraphWin;
//=== Vars


//---  Class Graph TX  ---//
//	Graph TX is window    // 
//	with OpenGL context.  // 
class txGraphWindow {
public:
	HDC  hDC;

	//---
	int x, y, w, h;
	char* title;
	int win_code;
	GLTFrame  *Camera;
	SYSTEMTIME  time_now, time_old;


public:	
	//--- MOUSE ---
	class txMouse {
	public:
		bool LeftButton;
		float rotz, rotx;
		int oldX, oldY;
	
		txMouse(){ rotx=-60.0; }
	} mouse;
	//=== MOUSE ===

public:
	txEngine *Eng;
	

public:
	txGraphWindow() { 
		title = DEFAULT_TITLE; 
		Eng = NULL;
		x = BEGIN_X; y = BEGIN_Y; w = BEGIN_W; h = BEGIN_H;
	};
	 
	txGraphWindow(txEngine *Eng_, char* s = DEFAULT_TITLE, 
		int x_ = 100, int y_ = 100, int w_ = 640, int h_ = 480)
			: x(x_), y(y_), w(w_), h(h_), title(s)
	{ 
		SetEngine(Eng_);
		Activate();
		Camera = &GraphWin->Eng->World->Camera;

		ResetTime(&time_old);
	};

	~txGraphWindow() { if (title != NULL) delete title; }

	virtual inline void  SetEngine(txEngine *eng) { Eng = eng; }

	virtual inline HDC  GetHDC() { return hDC; }

	virtual inline void  Activate() { GraphWin = this; }

	virtual inline void  WinMain();
	virtual inline void  WinExit();

	virtual inline void ResetTime(SYSTEMTIME *time) {
		time->wDay = 0;
		time->wMonth = 0;
		time->wDayOfWeek = 0;
		time->wHour = 0;
		time->wMinute = 0;
		time->wSecond = 0; 
		time->wYear = 0;
	}

	virtual inline unsigned long int  GetMillSec(SYSTEMTIME *t) {
		return 
			t->wSecond*1000 +
			t->wMilliseconds;
	}
};

void WinExit();

//------------------------- :: Functions :: ---------------------------

//--- CGraphTX - On Paint
void  OnPaint() 
{
#define  TIME_STEP 10

	GetSystemTime(&GraphWin->time_now);

	unsigned long int dt = 
	GraphWin->GetMillSec(&GraphWin->time_now) -
	GraphWin->GetMillSec(&GraphWin->time_old);

	if ( dt > TIME_STEP ) {
		GraphWin->Eng->World->World_Time += (dt / TIME_STEP);
		GraphWin->time_old = GraphWin->time_now;
	
		//--- OpenGL
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glPushMatrix();
	
		GraphWin -> Eng -> SceneGo();

		glPopMatrix();
		glutSwapBuffers();
		//=== OpenGL
	}

	glutPostRedisplay();
};


//--- On Mouse
void  OnMouse(int but, int state, int x, int y)
{
	switch (but) {
		case GLUT_WHEEL_UP : gltMoveFrameUp(GraphWin->Camera, 0.1); break;
		case GLUT_WHEEL_DOWN : gltMoveFrameUp(GraphWin->Camera, -0.1); break;

		case GLUT_LEFT_BUTTON : break;
	};

	glutPostRedisplay();
};


//--- On Special Key
void OnSpecialKey(int k1,int k2,int k3)
{
	GLTFrame  *Camera = &GraphWin->Eng->World->Camera;

	switch (k1) {
		case GLUT_KEY_UP    : gltMoveFrameForward(Camera,  0.2f); break;
		case GLUT_KEY_DOWN  : gltMoveFrameForward(Camera, -0.2f); break;
		case GLUT_KEY_LEFT  : gltRotateFrameLocalY(Camera, 0.02f); break;
		case GLUT_KEY_RIGHT : gltRotateFrameLocalY(Camera,-0.02f); break;
	}

	glutPostRedisplay();     
}


//--- On Key
void OnKeyboard(unsigned char k1,int k2,int k3)
{	
	switch (k1) {
		case 27 : GraphWin -> WinExit();	break;
		case 13 : GraphWin->Eng->World->World_Time++; glutPostRedisplay(); break;
	}
}


//--- On Resize
void OnResize(int w, int h)
{
	GraphWin -> Eng -> SceneResize(w,h);
}


//--- On Motion
void OnMotion(int x, int y)
{
	float dx = 0.125;
	int tx = x - GraphWin->mouse.oldX;
	if (tx > 0) 
		dx = -dx;
	else if (tx==0) dx = 0;
	
	if (x>GraphWin->Eng->World->Screen_Width-5 || x<5)
		glutWarpPointer(GraphWin->Eng->World->Screen_Width/2,y);
	
	if (y>GraphWin->Eng->World->Screen_Height-5 || y<5)
		glutWarpPointer(x,GraphWin->Eng->World->Screen_Height/2);

	GraphWin -> mouse.oldX = x; 
	GraphWin -> mouse.oldY = y;

	//gltRotateFrameLocalY(&GraphWin->Eng->World->Camera, dx);
	gltMoveFrameRight(&GraphWin->Eng->World->Camera, dx);

	glutPostRedisplay();
}


//--- CGraphTX - WIN EXIT
void  txGraphWindow :: WinExit()
{
	delete Eng;
	glutDestroyWindow(GraphWin -> win_code);
	exit(0);
}


//--- CGraphTX - WIN MAIN Function
void  txGraphWindow :: WinMain()
{
	int a = 1;
	char **s = new char*;
	(*s) = new char;

	glutInit( &a, s);
	glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );

	glutInitWindowPosition(x, y);
	glutInitWindowSize(w, h);
	win_code = glutCreateWindow(title);
	glutFullScreen();
	glutSetCursor(GLUT_CURSOR_NONE);

	//--- GLUT Funcs ---
	glutReshapeFunc( OnResize );
	glutDisplayFunc( OnPaint );
		
	glutKeyboardFunc( OnKeyboard );
	glutSpecialFunc( OnSpecialKey );

	glutMouseFunc( OnMouse );
	glutMotionFunc( OnMotion );
	//=== GLUT Funcs ===

	Eng -> SceneInit();
	
	//glutTimerFunc(40, OnTimer, 1);

	glutMainLoop();
};


#endif

 