/*------------------------------------------------------------------------------
//  Name: 
//
//  Date:
//
//  Description:
//
//  Assumptions:
//
//  Input:
// 
//  Outputs:
//
//
//--------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <GL/glut.h>        /* OpenGL include */

#define DEBUG               /* Coment to remove diagnostic messages */


/*-------------------------------------------------------------------------------
// Program Constants
//-------------------------------------------------------------------------------*/
/* initial window size constants (in pixels) */			
#define INIT_WINDOW_SIZE_WIDTH	400
#define INIT_WINDOW_SIZE_HEIGHT 400

/* initial window postion in screen coordinates (pixels)
//  i.e. w.r.t upper left corner of the screen, and positive y pointing downwards */
#define INIT_WINDOW_POS_X		200
#define INIT_WINDOW_POS_Y		150


/*----------------------------------
// Object and Color IDs (Menu IDs)
//----------------------------------*/
#define RED   1
#define GREEN 2
#define BLUE  3
#define WHITE 4

#define LINE     5
#define SQUARE   6
#define PENTAGON 7
#define CIRCLE   8
#define TRIANGLE 9

#define ERASE    10
#define QUIT     11

/*----------------------------------
// Object Properties
//----------------------------------*/
#define MAX_OBJECTS 20
#define RADIUS		50

#define PI      3.14159265358979

/* title of the drawing window	*/					
const char *WINDOWTITLE = { "OpenGL Sample  -- Bart Simpson" };


/* window background color definitions */
#define BLACK 0.0f,0.0f,0.0f    /* Background color */




typedef struct {
   int   type;
   float red;
   float green;
   float blue;
   int   x0, y0;
   float ang;
} PRIMATIVE_TYPE ;
/*-------------------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------------------*/
PRIMATIVE_TYPE  gObjects[MAX_OBJECTS];		  /* holds objects to draw */
int   gNumObjects;                            /* num objects to draw */
int   gCurrentObject;             
float gCurrentRed, gCurrentBlue, gCurrentGreen;
int   gPosX, gPosY;
int   gCur_Win_Width, gCur_Win_Height;
/*-------------------------------------------------------------------------------
// Function Prototypes
//-------------------------------------------------------------------------------*/
void InitGraphics(void);
void myDisplay(void);
void myChangeSize( int width, int height );
void myMouseFunc( int button, int state, int mouseX, int mouseY);
void InitMenu(void);
void MenuHandler(int id);

/*------------------------------------------------------------------------------
// Main Funtion
//------------------------------------------------------------------------------*/
int main( int argc, char **argv )
{

	/* Initalize OpenGL Toolkit */
	glutInit( &argc, argv);   

	/* Function to initalize graphics */
	InitGraphics();		  

	/*-------------------------------------------------------------
	//  Regisister event callback with glut
	//-----------------------------------------------------------*/
	glutMouseFunc(myMouseFunc);     /* handles mouse clicks */
	glutDisplayFunc( myDisplay );     /* handles drawing */	
	glutReshapeFunc( myChangeSize );  /* handles window resize */

	
	//------------------------------------------------------------------
	// Call OpenGL main loop. This function does not return until
	// the graphics window is closed or destroyed.
	//------------------------------------------------------------------
	glutMainLoop();

	return 0;
}

/*=====================================================================================
// OpenGL calls this function only once to initalize drawing properties.
//=====================================================================================*/
void InitGraphics(void) 
{

#ifdef DEBUG
	fprintf( stderr, "InitGraphics\n" );
#endif

	/* setup the display mode:					
	// ( *must* be done before call to glutCreateWindow() )		
	// ask for color, single-buffering:	*/	

	glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE );


	/* set the initial window configuration: */			
	glutInitWindowSize( INIT_WINDOW_SIZE_WIDTH, INIT_WINDOW_SIZE_HEIGHT );
    /* set windows initial postion in screen coordinates w.r.t upper left corner of screen */
	glutInitWindowPosition(INIT_WINDOW_POS_X, INIT_WINDOW_POS_Y);

	/* create the window and set its title:	*/			
	glutCreateWindow( WINDOWTITLE );
	glutSetWindowTitle( WINDOWTITLE );


	/* set the drawing window background color to black */
	glClearColor(BLACK, 0.0f);

	/* reset projection matrix  */
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	/* set default settings */
	glOrtho(0, INIT_WINDOW_SIZE_WIDTH, 0, INIT_WINDOW_SIZE_HEIGHT, 1.0, -1.0);

    InitMenu();

	/* Initalize Objects Array  */
	for (int i= 0; i< MAX_OBJECTS; i++) {
	    gObjects[i].type  = 0;
	    gObjects[i].red   = 0.0;
	    gObjects[i].green = 0.0;
	    gObjects[i].blue  = 0.0;
	    gObjects[i].x0 = gObjects[i].y0 = -1;
	    gObjects[i].ang = 0.0;
	}
	gNumObjects = 0;
	gCurrentObject = LINE;
	gCurrentRed = 1.0; gCurrentGreen = 0; gCurrentBlue = 0.0;
}

/*----------------------------------------------------------------------
// Call this function to draw a line
//---------------------------------------------------------------------*/
void DrawLine(int index){

#ifdef DEBUG
	fprintf(stderr, "DrawLine: %d \n", gObjects[index].type);
#endif 

}
/*----------------------------------------------------------------------
// Call this function to draw an N-gon
//---------------------------------------------------------------------*/
void DrawNGon(int index) {

#ifdef DEBUG
	fprintf(stderr, "DrawNGon: %d \n", gObjects[index].type);
#endif 


}
/*----------------------------------------------------------------------
// Call this function to draw all objects in object array
//---------------------------------------------------------------------*/
void DrawObjects(void) {
		

}

/*=====================================================================================
// OpenGL calls this function any time the drawing window needs to be redrawn.
//=====================================================================================*/
void myDisplay(void) 
{

#ifdef DEBUG
	fprintf( stderr, "Display\n" );
#endif 

	// Clear Screen
    glClear(GL_COLOR_BUFFER_BIT);

	if (gNumObjects > 0) DrawObjects();

	// Flush Drawing Commands
	glFlush();
}

/*=====================================================================================
// OpenGL calls this function just after the window is created and before its visible,
// and any time the window is resized by the user.
//=====================================================================================*/
void myChangeSize( int width, int height )
{

#ifdef DEBUG
	fprintf( stderr, "ChangeSize: w = %d, h = %d\n", width, height );  
#endif
	/* store new dimensions for later */
	gCur_Win_Width = width;
	gCur_Win_Height = height;

	/* set viewport to the same size as the newly resized window (in pixel units) */
	glViewport(0, 0, width, height);

	/* reset projection matrix  */
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	/* set drawing coordinates within viewport in physical units */
	glOrtho(0, width, 0, height, 1.0, -1.0);

	/* reset modelview matrix */
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

/*-----------------------------------------------------------------------------------
// OpenGl calls this function in response to a mouse event (mouse clicks).
//
// button = {GLUT_RIGHT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_LEFT_BUTTON}
//
// state  = {GLUT_UP, GLUT_DOWN}
//-----------------------------------------------------------------------------------*/
void myMouseFunc( int button, int state, int mouseX, int mouseY) {

	
	/* We are only interested in left clicks */
	if (button != GLUT_LEFT_BUTTON || state != GLUT_DOWN) return;
	
	/* Translate mouse values contained in mouseX and mouse Y
	// so they are relative to the bottom left corner of drawing window */
	gPosX = mouseX;
	gPosY = gCur_Win_Height - mouseY;
	

	
#ifdef DEBUG
	fprintf( stderr, "myMouseFunc: w = %d, h = %d %d\n", gPosX, gPosY, gNumObjects );  
#endif
}


/*----------------------------------------------------------------------------------
// This function is called to initalize a context menu
//----------------------------------------------------------------------------------*/
void InitMenu(void){

#ifdef DEBUG
	fprintf( stderr, "InitMenu: \n");  
#endif

	int menu, sub_menu;

	/* Create color submenu */
	sub_menu = glutCreateMenu(MenuHandler);
	glutAddMenuEntry("Red", RED);
	glutAddMenuEntry("Green", GREEN);
	glutAddMenuEntry("Blue", BLUE);
	glutAddMenuEntry("White", WHITE);

	/* create main context menu */
	menu = glutCreateMenu(MenuHandler);
    // attach submenu */
	glutAddSubMenu("Color", sub_menu);
	/* create object menu items */
	glutAddMenuEntry("Line", LINE);
	glutAddMenuEntry("Triangle", TRIANGLE);
	glutAddMenuEntry("Square", SQUARE);
	glutAddMenuEntry("Pentagon", PENTAGON);
	glutAddMenuEntry("Circle", CIRCLE);
	glutAddMenuEntry("Erase", ERASE);

	/* create a blank entry */
	glutAddMenuEntry("", -1);
	glutAddMenuEntry("Quit", QUIT);

	glutAttachMenu(GLUT_RIGHT_BUTTON);
}
/*----------------------------------------------------------------------------------
// This function is called by OpenGL in response to a context menu selection
//----------------------------------------------------------------------------------*/
void MenuHandler( int id) {
	
	switch (id) {
	case LINE:	   gCurrentObject = LINE;     break;
	case TRIANGLE: gCurrentObject = TRIANGLE; break;
	case SQUARE:   gCurrentObject = SQUARE;   break;
	case PENTAGON: gCurrentObject = PENTAGON; break;
	case CIRCLE:   gCurrentObject = CIRCLE;   break;
	case RED:   gCurrentRed = 1.0; gCurrentGreen = 0.0; gCurrentBlue = 0.0; break;
	case GREEN: gCurrentRed = 0.0; gCurrentGreen = 1.0; gCurrentBlue = 0.0; break;
	case BLUE:  gCurrentRed = 0.0; gCurrentGreen = 0.0; gCurrentBlue = 1.0; break;
	case WHITE: gCurrentRed = 1.0; gCurrentGreen = 1.0; gCurrentBlue = 1.0; break;
		
	case ERASE: 

		   break;
	case QUIT:
		   exit(0);
	       break;
	}

#ifdef DEBUG
	fprintf( stderr, "MenuHandler: %d\n", id);  
#endif

}
