#include <GL/glew.h>
#include <stdio.h>

// All IGLU headers are automatically included from "iglu.h"
#include "iglu.h"

// Headers for our display/rendering modes
#include "Mode_BlankDisplay.h"
#include "Mode_FontDisplay.h"
#include "Mode_TextureDisplay.h"
#include "Mode_SimpleModelDisplay.h"
#include "Mode_SimpleVideoDisplay.h"
#include "Mode_SierpinskiDisplay.h"
#include "Mode_SimpleReflectionsDisplay.h"

// Use the IGLU namespace throughout our code
using namespace iglu;

// These are handles to the two windows, should you need to modify their
//   behavior after window creation.
IGLUMultiDisplayWindow::Ptr         myWin = 0;

//The scene geometry consists of two objects: a wavefront obj file and a square 
IGLUOBJReader::Ptr      objCow     = 0;
IGLUOBJReader::Ptr      boxReader  = 0;

//Trackball for interaction
IGLUTrackball::Ptr		ball = 0;


// An (optional) window callback.  This function is guaranteed to be called *after* 
//    OpenGL initialization, but before the initialization functions of our 
//    individual display modes.
void OpenGLInitialization( void )
{	
	//Load obj files
	boxReader    = new IGLUOBJReader( "../../CommonSampleFiles/models/testBox.obj" );
	objCow       = new IGLUOBJReader( "../../CommonSampleFiles/models/cow.obj", IGLU_OBJ_UNITIZE );
	IGLUOBJMaterialReader::FinalizeMaterialsForRendering();

	// Create a virtual trackball
	ball         = new IGLUTrackball( myWin->w(), myWin->h() );
}

// An (optional) window callback that track changes when the mouse moves 
void Motion( int x, int y)
{
	ball->UpdateOnMotion(x, y);
}

// When the user clicks/releases in the main window, start/stop tracking with our trackball
void Button( int button, int state, int x, int y  )
{
	if(IGLU_EVENT_DOWN == state)
		ball->SetOnClick( x, y );
	else
		ball->Release();
}


int main(int argc, char** argv)
{
	// Create our main window
	myWin = new IGLUMultiDisplayWindow( 768, 768, 
		"Advanced IGLU Example:  A demonstration of a window with multiple display / rendering modes" );

	myWin->SetWindowProperties( IGLU_WINDOW_NO_RESIZE |	
								IGLU_WINDOW_DOUBLE |
								IGLU_WINDOW_REDRAW_ON_IDLE |
								IGLU_WINDOW_DEPTH ); 
	myWin->SetIdleCallback( IGLUWindow::NullIdle );
	myWin->SetPreprocessOnGLInit( OpenGLInitialization );
	myWin->SetActiveMotionCallback( Motion );
	myWin->SetMouseButtonCallback( Button );

	// Create the display modes we can render with in this demo.
	myWin->AddDisplayMode( new TextureDisplay() );
	myWin->AddDisplayMode( new SimpleModelDisplay() );
	myWin->AddDisplayMode( new SimpleVideoDisplay() );
	myWin->AddDisplayMode( new FontDisplay() );
	myWin->AddDisplayMode( new SierpinskiDisplay() );
	myWin->AddDisplayMode( new SimpleReflectionsDisplay() );
	myWin->AddDisplayMode( new BlankDisplay() );
	
	// Must be called after all calls to myWin->AddDisplayMode();
	myWin->CreateWindow( argc, argv );     
	
	// Start running our IGLU OpenGL program!
	IGLUMultiDisplayWindow::Run();
	return 0;
}
