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

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

// IGLU classes and constants are all inside the iglu namespace.
using namespace iglu;

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

// A pointers to our IGLU classes
IGLUTexture::Ptr         intRandTex   = 0;
IGLUTexture::Ptr         floatRandTex = 0;
IGLUShaderProgram::Ptr   shader       = 0;
IGLUVertexArray::Ptr     vertArray    = 0;

IGLUShaderProgram::Ptr   createUIFBO  = 0;
IGLUFramebuffer::Ptr     uiFBO        = 0;


IGLUFloat   lowerBound ( 0, IGLURange<float>(0,1), 0.01, "Display lower bound" );
IGLUFloat   upperBound ( 1, IGLURange<float>(0,1), 0.01, "Display upper bound" );


void display ( void )
{
	glClear( GL_COLOR_BUFFER_BIT );

	uiFBO->Bind();
	uiFBO->Clear();
		createUIFBO->Enable();
			vertArray->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
		createUIFBO->Disable();
	uiFBO->Unbind();

	shader->Enable();
		shader["lowerBound"] = lowerBound;
		shader["upperBound"] = upperBound;
		vertArray->DrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
	shader->Disable();
}


void OpenGLInitialization( void )
{ 
	// Create our unsigned int fbo
	uiFBO = IGLUFramebuffer::Create( GL_RGBA32UI, 512, 512 );

	// Load the texture with IGLU
	printf("(+) Creating a randomly populated texture...\n" );
	intRandTex = new IGLURandomTexture2D( 512, 512, GL_INT );  
	floatRandTex = new IGLURandomTexture2D( 512, 512, GL_FLOAT );

	printf("(+) Creating a shader to copy the texture on screen...\n");
	shader = new IGLUShaderProgram( "shaders/shaderTest.vert.glsl", "shaders/shaderTest.frag.glsl" );
	shader["uintRands"]  = uiFBO[ IGLU_COLOR0 ];
	shader["floatRands"] = floatRandTex;

	createUIFBO = new IGLUShaderProgram( "shaders/uiDrawTest.vert.glsl", "shaders/uiDrawTest.frag.glsl" );
	createUIFBO["intRands"]   = intRandTex;


	printf("(+) Creating a quad to texture...\n");
	vertArray = IGLUGeometry::CreateQuad( IGLU_GEOM_XY_PLANE );
}


int main(int argc, char** argv)
{
	// Put together our main window
	myWin = new IGLUWindow( 768, 768, "Simple IGLU Example:  Draw into and use an unsigned int framebuffer object" );
	myWin->SetWindowProperties( IGLU_WINDOW_NO_RESIZE |	
								IGLU_WINDOW_DOUBLE |
								IGLU_WINDOW_REDRAW_ON_IDLE |
								IGLU_WINDOW_W_FRAMERATE |
								IGLU_WINDOW_BLEND |
								IGLU_WINDOW_DEPTH ); 
	myWin->SetDisplayCallback( display );  
	myWin->SetIdleCallback( IGLUWindow::NullIdle );
	myWin->SetPreprocessOnGLInit( OpenGLInitialization );
	myWin->CreateWindow( argc, argv );     

	// Create a widget window to allow us to interact/change our IGLUVariables
	uiWin = new IGLUWidgetWindow( 300, 150, "UI Widget Window" );
	uiWin->AddWidget( &upperBound );
	uiWin->AddWidget( &lowerBound );

	// Tell our main window about the widget window... 
	myWin->SetWidgetWindow( uiWin );

	// Start the interaction loop
	IGLUWindow::Run();
	return 0;
}
