/*
    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

#ifdef HAVE_GL_GLUT_H
	#include <GL/glut.h>
#elif HAVE_OPENGL_GLUT_H
	#include <OpenGL/glut.h>
#endif


#ifdef HAVE_GL_GL_H
	#include <GL/gl.h>
#elif HAVE_OPENGL_GL_H
	#include <OpenGL/gl.h>
#endif

//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"

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.3" );

        // 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 | GL_DEPTH_BUFFER_BIT);
	int empty = 0;

	#ifndef HAVE_LIBPTHREAD
	Calcs();
	#endif

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

		glLoadIdentity();
		glTranslatef ( 0.0, 0.0, -25 );

		glColor3f(1.0, 0.0, 0.0);//print timer in red
		glRasterPos2f(0.0, 0.0);
	
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'Y');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'o');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'u');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,' ');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'L');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'o');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'s');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'e');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'!');
		glRasterPos2f(-1.0, -1.0);
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'E');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'n');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'t');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'e');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'r');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,' ');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'t');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'o');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,' ');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'C');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'o');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'n');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'t');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'i');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'n');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'u');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'e');

	}

         
        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);
                glRasterPos2f(5.0, -17.0);
                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'S');
                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'c');
                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'o');
                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'r');
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'e');
                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,':');
                glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,' ');
		scorestring[strlen(scorestring)-1]='\0';
		empty = sprintf(scorestring, "%lf", score);
		if( gamepaws == 1)
		{
			strcat(scorestring, " PAUSED, press p to continue");
		}
                for(i = 0; scorestring[i] != '\0'; i++)
                {
                        glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,scorestring[i]);
                    
                }

	
        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 );
    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, 30.0 );
        
        // Select the Modelview matrix
    glMatrixMode( GL_MODELVIEW );
}

