/*
    This file is part of lspong.
    lspong is a loose representation of the old pong game we all remember and love.
    Copyright (C) 2009  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 <stdio.h>   
#include <stdlib.h>
#include <string.h>

//#include "config.h"
#ifdef HAVE_LIBPTHREAD
#include <pthread.h>
#endif

#include <GL/glut.h>
#include <GL/gl.h>
//include <unistd.h>
#include <time.h>
#include <sys/time.h>
//define SETTINGS 1
#define RESTART 2
#define PAUSED 3
#define EXIT 4
//#include "test.h"
//#include "calcs.h"
#include "ls_shapes.h"

void OpenGLInit(void);

/*
pthread_mutex_t    mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t    mutex1;
pthread_mutex_t    mutex2;
pthread_mutex_t    mutex3;
*/
                        
//void *Calcs_Thread(void *null);



static void Animate(void );
static void ResizeWindow(int w, int h);
int glutCreateMenu(void (*func)(int value));
void glutAddMenuEntry(char *name, int value);
void glutAttachMenu(int button);  
void processMenuEvents(int option);
//static void Setting(void);
	void glutDestroyWindow(int windowID); 
struct timespec ts;
struct timeval starttime,endtime;
//struct tm *local;
//time_t t;


void keyboard (unsigned char key, int x, int y);
//void keyboardUp (unsigned char key, int x, int y);
bool ignoreRepeats = false;
        //int i;
	//int a;
        int coord1 = 0;
        int direction = 1;
	int coord2 = 0;
	int coord3 = -25;
	int coord4 = -22;
	int coord5 = 0;
	int coord6 = -25;
	int coord7 = 22;
	int coord8 = 0;
	int coord9 = -25;
	int angle1 = 0;
	int gamepaws = 0;
	double fps = 0;
	double time1, time2;
	//int red, green, blue, white;
	double score = 0;
	int sleepnsec = 100000000;
	int sleepsec = 0;
	char scorestring[sizeof(double)+33];

//#include "calcs.h"

#ifdef HAVE_LIBPTHREAD
int a;
#include "threads.h"
#endif

void createGLUTMenus() {

	int menu;

	// create the menu and
	// tell glut that "processMenuEvents" will 
	// handle the events
	menu = glutCreateMenu(processMenuEvents);
	
	//add entries to our menu
	//glutAddMenuEntry("Settings",SETTINGS);
	glutAddMenuEntry("Restart",RESTART);
	glutAddMenuEntry("Pause",PAUSED);
	glutAddMenuEntry("Exit",EXIT);
	
	// attach the menu to the right button
	glutAttachMenu(GLUT_RIGHT_BUTTON);
}

void processMenuEvents(int option) {

	switch (option) {

		/*case SETTINGS :
			glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
			glutInitWindowPosition( 0, 0 );
			glutInitWindowSize( 800, 600 );
			glutCreateWindow( "Testing 123" );
        		// Initialize OpenGL.
    			//OpenGLInit();
        		// Set up the callback function for resizing windows
    			glutReshapeFunc( ResizeWindow );
			glutDisplayFunc( Setting);
			glutKeyboardFunc (keyboard);
			//glutMainLoop(  );
			break;
		*/
		case RESTART :
                	coord1 = 0;
                	direction = 1;
                	coord2 = 0;
                	coord3 = -25;
                	coord4 = -22;
                	coord5 = 0;
                	coord6 = -25;
        		coord7 = 22;
        		coord8 = 0;
        		coord9 = -25;
                	angle1 = 0;
			score = 0;
        		sleepnsec = 100000000;
        		sleepsec = 0;
			break;
		case PAUSED :
			if (gamepaws == 0){
				gamepaws = 1;
			}else{
				gamepaws = 0;
			}
			break;
		case EXIT :
			exit (0); 
			break;
	}
}


void special (int key, int x, int y)
{

  switch (key) { 
    case GLUT_KEY_UP:
      break;

    case GLUT_KEY_DOWN:
      break;

    case GLUT_KEY_RIGHT:
	if ((angle1 != 6) && (coord5 >= -14) && (gamepaws == 0))
	{
		coord5--;
	}
      break;

    case GLUT_KEY_LEFT:
	//printf("left key pressed\n");
	if ((angle1 != 6) && (coord5 <= 14)&& (gamepaws == 0))
	{
		coord5++;

	}
      break;

 }

}
        
void keyboard(unsigned char key, int x, int y)
{
        if (key==27)
        {
                        //27 is the ascii code for the ESC key
        exit (0); //end the program
        }else if (key==13){
                coord1 = 0;
                direction = 1;
                coord2 = 0;
                coord3 = -25;
                coord4 = -22;
                coord5 = 0;
                coord6 = -25;
                coord7 = 22;
                coord8 = 0;
                coord9 = -25;
                angle1 = 0;
		score = 0;
                sleepnsec = 100000000;
                sleepsec = 0;

	}else if (key==112){
        	if (gamepaws == 0)
			gamepaws = 1;
                else
                        gamepaws = 0;

	}
		//if (key==
		//void glutDestroyWindow(int windowID);
}

/*
void keyboard2 (unsigned char key, int x, int y)
{

        if (key==13)
        {
                angle1=0;
        }

    
}
*/

int main( int argc, char** argv )   
{
	//int i;
        //int coord1 = 0;
        //int direction = 1;   
	//int angle1 = 0;
        glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB );
	//| GLUT_DEPTH );

        // Create and position the graphics window
	glutInitWindowPosition( 0, 0 );
	glutInitWindowSize( 1600, 1200 );
	glutCreateWindow( "lspong v0.1.2" );

        // Initialize OpenGL.
	OpenGLInit();
        // Set up the callback function for resizing windows
	glutReshapeFunc( ResizeWindow );
 
        // Callback for graphics image redrawing
	glutDisplayFunc( Animate);

	glutIgnoreKeyRepeat(ignoreRepeats);

	glutSpecialFunc(special);
	glutKeyboardFunc (keyboard);
	//glutKeyboardFunc (keyboard2);

	//glutSpecialFunc(special);
	createGLUTMenus();

	#ifdef HAVE_LIBPTHREAD
	pthread_t thread;
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        //pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
	a = pthread_create(&thread, &attr, Calcs_Thread, NULL);
	#endif

	gettimeofday(&starttime, NULL);
        glutMainLoop(  );

	exit(1);
}

/*
static void Setting(void)
{
	int i = 0;
	char *settings = "Settings will go here.";
	char *settings2 = "Press ESC to close.";
	//settings[strlen(settings)-1]='\0';
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                glLoadIdentity();
                glTranslatef ( 0.0, 0.0, -25 );
                glColor3f(1.0, 0.0, 0.0);
                glRasterPos2f(0.0, 0.0);
	//while(settings[i] != '/0')
	//{
	//char *c;
	//c=settings;
	while(*settings != '\0') 
	{
    		//glutBitmapCharacter(font, *c);
  		//}
		//}

		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,*settings);
		//i++;
		*settings++;
	}
        while(*settings2 != '\0')
        {
                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,*settings2);
                //i++;
                *settings2++;
        }

	//glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'Y');

	sleep (3);
	//glutDestroyWindow(2);
        glFlush();
        glutSwapBuffers();   
        glutPostRedisplay();            // Request a re-draw for animation purposes
        glutDestroyWindow(2);

}
*/



static void Animate(void)
{


	//char scorestring[sizeof(double)+33];
	int i = 0;
	//glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	int empty = 0;

	#ifndef HAVE_LIBPTHREAD
	//Calcs();
	#endif


//		glLoadIdentity();
//		glTranslatef ( 0.0, 0.0, -25 );
//
//		glColor3f(1.0, 0.0, 0.0);//print timer in red
//		glRasterPos2f(0.0, 0.0);

	int y1;
	double x_coord;
/*
	for(x1=-800; x1<=800; x1+=50) {
		glBegin(GL_POINTS);
        	for(y1=-600; y1 <= 600; y1+=1) {
			glColor4f( 0, 255, 0, 0);
			glVertex3f(x1, y1, 0);
		}
               	glEnd();


        }


glBegin(GL_LINES);

glColor4f( 0, 255, 0, 0);

for(x1=0; x1<=1600; x1+=50) {
	//for(y1=0; y1 <= 1200; y1+=1) {

		glVertex3f(x1, y1, -25); // origin of the line
		glVertex3f(x1, y1+600, -25); // ending point of the line

	//}
}

glEnd( );
*/






glLoadIdentity();
glTranslatef(0, 0, -10);
glColor4f( 0, 255, 0, 0);
//glBegin(GL_LINES);

/*
        glLoadIdentity();
        glTranslatef ( 0, 0, -10 );
        glColor3f( 2.0, 2.0, 0.0 );
        glRectf(-0.50f,2.00f, 0.50f, -2.00f);


        glLoadIdentity();
        glTranslatef ( 0, 0, -10 );
        glColor3f( 2.0, 2.0, 0.0 );
        glRectf(-0.50f,2.00f, 0.50f, -2.00f);


//############################################

glLoadIdentity();
glTranslatef ( 0, 0, -10 );
glColor3f( 2.0, 2.0, 0.0 );
glBegin(GL_POLYGON); 
glVertex3f(-5.0, 5.0, 0);
glVertex3f(-5.0,-5.0, 0); 
glVertex3f(5.0, -5.0, 0);	
glVertex3f(5.0, 5.0, 0);
glEnd();


//glBegin(GL_POLYGON);
//glVertex3f(-5.0, 5.0, 5);
//glVertex3f(-5.0,-5.0, 5);
//glVertex3f(5.0, -5.0, 5);
//glVertex3f(5.0, 5.0, 5);

//glEnd();

glPushMatrix();
glColor3f( 0.0, 0.0, 2.0 );  
glTranslatef(0.0, 0.0, -2.0);
glutSolidCube(2);
//glPopMatrix();


glColor3f( 0.0, 2.0, 2.0 );  
glTranslatef(1.0, 1.0, coord5);
glutSolidCube(2);


glPopMatrix();
glColor3f( 2.0, 2.0, 0.0 );
glTranslatef(2.0, 2.0, -2.0);
glutSolidCube(2);

//glPushMatrix();

glColor3f( 0.0, 2.0, 0.0 );
glTranslatef(3, 3, coord5);
glutSolidCube(2);

//glPopMatrix();

//glutWireCube(2);

//glScalef(25.0, 25.0, 25.0);
*/






        //glColor4f(150.0, 150.0, 0.0, 255.0);
        ls_cube(0, 0, 0, 6, 6, 6);

//glutSolidCube(2);









/*
for(x_coord=0; x_coord<=20; x_coord+=1) {
	//glLoadIdentity();
	//glColor4f( 0, 255, 0, 0);
	//glTranslatef(x_coord,0.0f,0.0f);

	//glBegin(GL_LINES);
	glVertex3f(x_coord, 0.0, 0);
	glVertex3f(x_coord, 4.0, 0);
	//glEnd( );
}
glEnd( );


glLoadIdentity();
glTranslatef(0, 0, -10);
glColor4f( 0, 255, 0, 0);
glBegin(GL_LINES);
glVertex3f(0.0, 0.0, 0);   
glVertex3f(50, 1200.0, 0);
glEnd( );


glBegin(GL_LINES);
glColor4f( 0, 255, 0, 0);
glVertex3f(50, 1.0, 0);
glVertex3f(50, 1200.0, 0);

glColor4f( 0, 255, 0, 0);
glVertex3f(100, 1.0, 0);
glVertex3f(100, 1200.0, 0);

glColor4f( 0, 255, 0, 0);
glVertex3f(150, 1.0, 0);
glVertex3f(150, 1200.0, 0);

glEnd( );
*/


/*
glBegin(GL_POINTS);

glVertex3f(0, 0, -25);
glVertex3f(1, 1, -25);
glVertex3f(2, 2, -25);
glVertex3f(15, 15, -25);

glVertex3f(150, 150, -25);
//glVertex3f(100, 100, -25);
//glVertex3f(150, 150, -25);
//glVertex3f(200, 200, -25);
//glVertex3f(750, 750, -25);


glEnd( );
*/





/*         
        glLoadIdentity();    
        glTranslatef ( coord1, coord2, coord3 );     
        glColor3f( 1.0, 1.0, 0.0 );
	glutSolidSphere( 0.50, 300, 300 );


        glLoadIdentity();
        glTranslatef ( coord7, coord8, coord9 );
        glColor3f( 2.0, 2.0, 0.0 );
        glRectf(-0.50f,2.00f, 0.50f, -2.00f);


	glLoadIdentity();
	glTranslatef ( coord4, coord5, coord6 );
	glColor3f( 2.0, 2.0, 0.0 );
	glRectf(-0.50f,2.00f, 0.50f, -2.00f);
	

	glLoadIdentity();
	glTranslatef ( 0.0, 0.0, -25 );
	glColor3f(1.0, 0.0, 0.0);
*/

	
        if((angle1 != 6) && (gamepaws == 0))
        {       

		time2++;
		gettimeofday(&endtime, NULL);
		time1=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;

		if (time1 >= 1)
		{
		fps = time2 / time1;
        	//printf("time1: %lf\n", time1);
                //fps = time2 / time1;
                gettimeofday(&starttime, NULL);
                time2 = 0;
		}

                glLoadIdentity();
                glTranslatef ( 0.0, 0.0, -25 );
                glColor3f(1.0, 0.0, 0.0);
                glRasterPos2f(17.0, 17.0);
                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,' ');
                //glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,' ');
                //glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,' ');
                scorestring[strlen(scorestring)-1]='\0';
         
                empty = sprintf(scorestring, "%lf", fps);
         
                //printf("%lf\n", fps);
                for(i = 0; scorestring[i] != '\0'; i++)
                {
                        glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,scorestring[i]);
        
                }
        }



	glFlush();
	glutSwapBuffers();
	glutPostRedisplay();            // Request a re-draw for animation purposes

	
}


void renderBitmapString(
		float x, 
		float y, 
		float z, 
		void *font, 
		char *string) {  
  char *c;
  glRasterPos3f(x, y,z);
//glColor3f( 1.0, 1.0, 0.0 );
  for (c=string; *c != '\0'; c++) {
    glutBitmapCharacter(font, *c);
  }
//return (0);
}



/*

void OpenGLInit(void)
{       
        glShadeModel( GL_FLAT );
        glClearColor( 0.0, 0.0, 0.0, 0.0 );
        glClear(GL_COLOR_BUFFER_BIT);
        glDisable( GL_DEPTH_TEST );
}


static void ResizeWindow(int w, int h)  
{
        float aspectRatio;
        h = (h == 0) ? 1 : h;
        w = (w == 0) ? 1 : w;
        glViewport( 0, 0, w, h );       // View port uses whole window
        aspectRatio = (float)w/(float)h;
         
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
gluPerspective(10.0f,aspectRatio,-1.0f,10.0f);
        //glOrtho (0, w, h, 0, 0, 1);
        glMatrixMode( GL_MODELVIEW );
}


*/






void OpenGLInit(void)
{       
    glShadeModel( GL_FLAT );
    glClearColor( 0.0, 0.0, 0.0, 0.0 );
    glClearDepth( 1.0 );
    glEnable( GL_DEPTH_TEST );
}

static void ResizeWindow(int w, int h)
{
    float aspectRatio;
        h = (h == 0) ? 1 : h;
        w = (w == 0) ? 1 : w;
        glViewport( 0, 0, w, h );       // View port uses whole window
        aspectRatio = (float)w/(float)h;
        
        // Set up the projection view matrix (not very well!)
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    gluPerspective( 70.0, aspectRatio, 1.0, 100.0 );
      //  glLoadIdentity();
	//glOrtho (0, w, h, 0, 0, 1);
        // Select the Modelview matrix
    glMatrixMode( GL_MODELVIEW );
}


