/*
    Living Realms is a primate evolution simulator.
    Copyright (C) 2011  Sterling Pickens

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "lrstats-gl.h"
#define TOGGLE 0
#define PAUSED 1
#define EXIT_AND_SAVE 2
#define EXIT_NO_SAVE 3
#define LEGEND_W 3600
#define LEGEND_H 400

unsigned char *legend_img;
char *Legend_Filename;
GLuint Image_Texture;
GLuint Legend_Texture;
double Eye_X = 0.0;
double Eye_Y = -0.5;
double Eye_Z = -2.2;
char scorestring[32];
struct timeval starttime,endtime;
int Toggle_Image_Type = 0;
int Toggle_Paused = 0;

static void processMenuEvents(int option);
static void special(int key, int x, int y);
static void Frames(double fps);
static void BindTexture(void);
static void BindLegend(void);

static void createGLUTMenus(void){
	int menu;
	menu = glutCreateMenu(processMenuEvents);
	glutAddMenuEntry("Toggle Pause OpenGL updates",PAUSED);
	glutAddMenuEntry("Exit",EXIT_NO_SAVE);
	glutAttachMenu(GLUT_RIGHT_BUTTON);
}

static void processMenuEvents(int option) {
	switch(option){
		case PAUSED :
			Toggle_Paused ^= 1;
			break;
		case EXIT_NO_SAVE :
			printf("Exiting Program Without Saving!!\n");
			No_Exit = 2;
			glDeleteTextures( 1, &Image_Texture );
			glDeleteTextures( 1, &Legend_Texture );
			exit(1);
			//need to fix !
			//return;
			break;
	}
}

static void special(int key, int x, int y){
	switch(key){
		case GLUT_KEY_UP:
			Eye_Y+=Eye_Z/10;
			break;
		case GLUT_KEY_DOWN:
			Eye_Y-=Eye_Z/10;
			break;
		case GLUT_KEY_RIGHT:
			Eye_X-=Eye_Z/10;
			break;
		case GLUT_KEY_LEFT:
			Eye_X+=Eye_Z/10;
			break;
		case GLUT_KEY_PAGE_UP:
			Eye_Z+=Eye_Z/10;
			break;
		case GLUT_KEY_PAGE_DOWN:
			Eye_Z-=Eye_Z/10;
			break;
	}
}

static void Frames(double fps){
	(void)memset(scorestring, '\0', 32);
	int empty = 0;
	empty = sprintf(scorestring, "%.02lf", fps);
	float pos[3] = {-1, 10, -25};
	int i = 0;
    glPushMatrix();
    glLoadIdentity();
	pos[0]+=0.1;
	glColor3f(1.0, 0.0, 0.0);
	glRasterPos3f(pos[0], pos[1], pos[2]);
	glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'F');
	glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'P');
	glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'S');
	glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,':');
	glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,' ');
	for(i = 0; scorestring[i] != '\0'; i++){
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, scorestring[i]);
	}
	glPopMatrix();
}

static void BindLegend(void){
	glPushMatrix();
	glEnable(GL_TEXTURE_2D);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, LEGEND_W, LEGEND_H, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)legend_img);
	glBindTexture( GL_TEXTURE_2D, Legend_Texture );
	glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	const float x = 1;
	const float y = 1;
	glTranslatef(0.0, -0.8182, 0.0 );
	glScalef(1.0, 0.8181, 1.0);
	glColor3f(1.0f,1.0f,1.0f);
	glBegin (GL_QUADS);
	glTexCoord2d(0.0,y); glVertex2d(x,-1.0*y);
	glTexCoord2d(0.0,0.0); glVertex2d(x,y);
	glTexCoord2d(x,0.0); glVertex2d(-1.0*x,y);
	glTexCoord2d(x,y); glVertex2d(-1.0*x,-1.0*y);
	glEnd();
	glDisable(GL_TEXTURE_2D);
	glPopMatrix();
}

static void BindTexture(void){
	glPushMatrix();
	glEnable(GL_TEXTURE_2D);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)ia->image);
	glBindTexture( GL_TEXTURE_2D, Image_Texture );
	glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	const float x = 1;
	const float y = 1;
	glTranslatef(0.0, 0.1819, 0.0);
	glScalef(1.0, 0.1818, 1.0);
	glColor3f(1.0f,1.0f,1.0f);
    glBegin (GL_QUADS);
    glTexCoord2d(0.0,y); glVertex2d(x,-1.0*y);
    glTexCoord2d(0.0,0.0); glVertex2d(x,y);
    glTexCoord2d(x,0.0); glVertex2d(-1.0*x,y);
    glTexCoord2d(x,y); glVertex2d(-1.0*x,-1.0*y);
    glEnd();
	//This is how texture coordinates are arranged
	//
	//  0,1   ---   1,1
	//       |     |
	//       |     |
	//       |     |
	//  0,0   ---   1,0
	glDisable(GL_TEXTURE_2D); 
	glPopMatrix();
}

static void display(void){
	static struct timespec ts;
    ts.tv_sec = 0;
    ts.tv_nsec = 50000000;
	static double time1 = 2;
	static double frame_c = 0;
	static double fps = 0;
	if(!Toggle_Paused){
		glClearColor (0.0,0.0,0.0,1.0);
		glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glLoadIdentity();
		gluLookAt ( Eye_X, Eye_Y, Eye_Z,  Eye_X, Eye_Y, 0.0, 0.0, 0.1, 0.0);
		if(No_Exit != 1){
			glDeleteTextures( 1, &Image_Texture );
			glDeleteTextures( 1, &Legend_Texture );
			exit(1);
			//return;
		}
		BindLegend();
		BindTexture();
		frame_c++; //frame counter
		if(time1 > 1){
			gettimeofday(&endtime, NULL);
			time1=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
			fps = frame_c / time1;
			gettimeofday(&starttime, NULL);
			frame_c = 0;
		}else{
			gettimeofday(&endtime, NULL);
			time1=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
		}
		Frames(fps);
		glutSwapBuffers();
		glutPostRedisplay();
	}else{
		sleep(1);
	}
}

static void reshape(int w, int h){
	GLfloat aspect = (GLfloat)WIDTH / (GLfloat)(HEIGHT+LEGEND_H+4.4);;
    glViewport (0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
	gluPerspective (60, (GLfloat)w / (GLfloat)h/aspect, 0.0 , 100.0);
    glMatrixMode (GL_MODELVIEW);
}

void Run_GL(void){
	glutInitDisplayMode (GLUT_DOUBLE| GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(GLWIDTH, GLHEIGHT);
	glutInitWindowPosition(0, 0);
	glutCreateWindow(LR_NAME" "LR_VERSION);
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutIgnoreKeyRepeat(0);
	glutSpecialFunc(special);
	Legend_Filename = (char *)malloc(strlen("legend.png") + 1);
	(void)strcpy(Legend_Filename, "legend.png");
	legend_img = (unsigned char *)malloc(LEGEND_H * LEGEND_W * 3);
	if(Open_Convert_Legend(legend_img, Legend_Filename) != 0){
		printf("Png Error Exiting!\n");
		free(legend_img);
		free(Legend_Filename);
		No_Exit = 0;
		exit(1);
		//return;
	}
	free(Legend_Filename);
	glGenTextures( 1, &Image_Texture );
	glGenTextures( 1, &Legend_Texture );
	createGLUTMenus();
	glutMainLoop();
	//;
}
