/*
    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 <GL/glut.h>
#include <GL/gl.h>
#include <unistd.h>
#include <time.h>
//define SETTINGS 1
#define RESTART 2
#define PAUSED 3
#define EXIT 4


void OpenGLInit(void);

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;
void keyboard (unsigned char key, int x, int y);
//void keyboardUp (unsigned char key, int x, int y);
bool ignoreRepeats = false;
        //int i;
        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;
	//int red, green, blue, white;
	double score = 0;
	int sleepnsec = 100000000;
	int sleepsec = 0;

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" );
/*
    glutCreateMenu(void (*func)(int value));
    glutAddMenuEntry(char *name, int value);
    glutAttachMenu(GLUT_LEFT_BUTTON);  
*/

//createGLUTMenus();
//glutIgnoreKeyRepeat(ignoreRepeats);
//glutKeyboardUpFunc (keyboardUp);

//glutKeyboardFunc (keyboard);

        // 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();

//glutKeyboardFunc (SpecialKeyboardChars);
//while (1==1) {
        // Start the main loop.  glutMainLoop never returns.
        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)
{
	//if (pause == 0)
	//{

	char scorestring[sizeof(double)+33];
	int i = 0;
	//int runcount = 0;
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	int empty = 0;
        //ts.tv_sec = 0;   
        //ts.tv_nsec = 100000000;
       //nanosleep (&ts, NULL);	

        if((coord1 == 21) && (gamepaws == 0))
        {
		/*
        	if (angle1 != 6 && coord8 >= -14)
        	{
                	coord8--;
        	}
                if (angle1 != 6 && coord8 <= 14)
                {
                        coord8++;
                }*/
		
		srand ( time(NULL) );
		coord8 = rand() % 4 -2;
		coord8 = coord2 + coord8;

		//glLoadIdentity();
                if(coord2 == coord8)
                {
                        angle1 = 0;
                }else if((coord2 >= coord8-2) && (coord2 < (coord8-1))){
                        //implement 45 degree downward trajectory
                        angle1 = -2;
                }else if((coord2 >= coord8-1) && (coord2 < (coord8))){
                        //implement 22.5 degree downward trajectory
                        angle1 = -1;
                }else if((coord2 <= coord8+2) && (coord2 > (coord8+1))){
                        //implement 45 degree upward trajectory
                        angle1 = 2;
                }else if((coord2 <= coord8+1) && (coord2 > coord8)){
                        angle1 = 1;
                }
		
	}

	if((coord1 == -21) && (gamepaws == 0))
	{
		if(coord2 == coord5)
		{
			angle1 = 0;
		}else if((coord2 >= coord5-2) && (coord2 < (coord5-1))){
			//implement 45 degree downward trajectory
			angle1 = -2;
		}else if((coord2 >= coord5-1) && (coord2 < (coord5))){
			//implement 22.5 degree downward trajectory
			angle1 = -1;
		}else if((coord2 <= coord5+2) && (coord2 > (coord5+1))){
			//implement 45 degree upward trajectory	
			angle1 = 2;
		}else if((coord2 <= coord5+1) && (coord2 > coord5)){
			angle1 = 1;
		}else{
			//game over
			angle1 = 6;
			//score = score - 5;
		}
	}

                if((coord1 == -21) && (angle1 != 6))
                { 
                        score += 5;
                }


        if((angle1 != 6) && (gamepaws == 0))
        {
		//coord2 = coord2 + angle1;

		if(coord2 == 16)
		{
			angle1 = angle1 * -1;
		}
		if(coord2 == -16)
		{
			angle1 = abs(angle1); 
		}


                coord2 = coord2 + (angle1);


        	if (coord1 == 21)   
        	{
                	direction = 0;
        	}
        	if (coord1 == -21)
        	{
                	direction = 1;
        	}
        	if(direction == 1)
        	{
                	coord1++;
        	}else{   
                	coord1--;
        	}
		//if(coord1 == -21)
		//{
		//	score += 5;
		//}
	}else if(gamepaws == 0){

		//score -= 5;
		glLoadIdentity();
		glTranslatef ( 0.0, 0.0, -25 );
		//glRasterPos2f(float x, float y);
		//glRasterPos3f(0, 0, -25);
		//glColor3f( 1.0, 1.0, 0.0 );
		//glColor3f(0.0, 1.0, 0.0); 


		glColor3f(1.0, 0.0, 0.0);//print timer in red
		glRasterPos2f(0.0, 0.0);
	
		//glRasterPos3f(0, 0, -25);
		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');

		//glRasterPos3f(0, 0, -25);
		//renderBitmapString(0, 0, -25, GLUT_BITMAP_HELVETICA_10,'You Lose!');
	}



	//}else{




        // Clear the redering window
        //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // Clear the current matrix (Modelview)
         
        glLoadIdentity();    
        // Back off eight units to be able to view from the origin.
                
        glTranslatef ( coord1, coord2, coord3 );


        // Rotate the plane of the elliptic
        // (rotate the model's plane about the x axis by fifteen degrees)
        //glRotatef( 15.0, 1.0, 0.0, 0.0 );
        
    	// Draw the sun     -- as a yellow, wireframe sphere
        glColor3f( 1.0, 1.0, 0.0 );
    	//glutWireSphere( 4.0, 80, 80 );

	glutSolidSphere( 0.50, 300, 300 );

	//glutSolidCube(1.0);
	//glutSolidCube(1.0);
	//empty = 0;
	//tv_usec
        /* Delay for a bit */
	//        ts.tv_sec = 0;
	//        ts.tv_nsec = 100000000;
	//        nanosleep (&ts, NULL);

        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 );
	//printf("coord2 %d\n", coord2);

	glColor3f( 2.0, 2.0, 0.0 );
	//glutSolidCube(1.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(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");
			//scorestring[strlen(scorestring)-1]='\0';
			//glRasterPos2f(-13.0, -17.0);
		}
                for(i = 0; scorestring[i] != '\0'; i++)
                {
                        glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,scorestring[i]);
                    
                }
		//scorestring[strlen(scorestring)-1]='\0';


	//nanosleep (100, empty);
	//nanosleep(tv_usec, empty);
	glFlush();
	glutSwapBuffers();
	glutPostRedisplay();            // Request a re-draw for animation purposes

	if(sleepnsec > 5000000)
	{
		sleepnsec -= 100000; 
	}
        ts.tv_sec = sleepsec;
        ts.tv_nsec = sleepnsec;

        nanosleep (&ts, NULL);


}


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 );
}

