#include <stdio.h>
#include <stdlib.h>


#include <gl/glut.h>
#include <time.h>  
 
/* Some <math.h> files do not define M_PI... */
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

#include "GameView.h"


#ifdef _WIN32
#define drand48() (((float) rand())/((float) RAND_MAX))
#define srand48(x) (srand((x)))
#endif

/** Global Variable storing the current Game Section
It can point either to GS or to GI */
GameView *Game;

/** Global Variable storing the Game Session */
GameView GS;

/** Glut Callback on pression of  keys.*/
void Key(unsigned char key, int x, int y)
{

    Game->setKey(key);
}

/** Glut Callback on pression of arrow keys.*/
void  SpecialKey(int key, int x, int y)
{
    Game->setSKey(key);
}
/** Glut Callback on release of arrow keys.
It should stop the (side and back) thrust and the rotation of the ship.
*/
void SpecialKeyUp(int key, int x, int y)
{
    Game->setSKeyUp(key);
}



/** Glut Callback on Window Reshape.*/
void Reshape(GLsizei w, GLsizei h)
{ 
    Game->Reshape(w,h);
  
}       

/** Glut Idle Callback .
It is continuously called when events are not
being received. It post a refresh request in order to make the animation
as smoother as possible. It is enabled/disable by the Visible Callback
@see Visible
*/

void Idle(void)
{
    
    glutPostRedisplay();
}
/** Glut Callback on Window visibility.
It is called when the glut window change its visiblitiy status.
When the window is hidden we should stop the idle callback (and viceversa).
*/
void Visible(int vis)
{
 if (vis == GLUT_VISIBLE)
      glutIdleFunc(Idle);
 else
      glutIdleFunc(NULL);
}


/** Glut Callback to Draw everything.
It clear the screen, call the GameView
Update(), TargetCamera and Draw() and swap the buffers.
*/
void Display(void)
{ 
  static int lasttime;
  int dt;
  dt=glutGet(GLUT_ELAPSED_TIME)-lasttime;
  lasttime=glutGet(GLUT_ELAPSED_TIME);

  Game->Update();
  Game->TargetCamera();
  Game->Draw();

  glutSwapBuffers();
}
/** Glut Callback to Mouse active movement*/
void processMouseActiveMotion(int x, int y) 

{
        Game->setMouse(x,y);
        Game->move();
    
    
}
/** Glut Callback to press botton Mouse*/
void Mouse(int button, int state, int x, int y)
{
    Game->setMouse(x,y);
    switch (button) 
    {
    case GLUT_LEFT_BUTTON:
                if (state==GLUT_DOWN) Game->b_left=true;
                if (state==GLUT_UP) Game->b_left=false;
                break;
    case GLUT_RIGHT_BUTTON:
                if (state==GLUT_DOWN) Game->b_right=true;
                if (state==GLUT_UP) Game->b_right=false;
                break;
    default: break;
    }
}

/** The Classical Main Function
It has to setup all the glut callbacks, initialize Openglstatus
and start the glutMainLoop.
*/

int main(int argc, char** argv)
{ 

  Game=&GS;
  glutInit(&argc, argv);
  glutInitWindowSize(800, 600);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );
  glutCreateWindow("Marble Game");

  glutReshapeFunc(Reshape);
  glutDisplayFunc(Display);
  glutIdleFunc(Idle);
  glutVisibilityFunc(Visible);
  glutKeyboardFunc(Key);    
  glutSpecialFunc(SpecialKey);  
  glutSpecialUpFunc(SpecialKeyUp);  

  glutMouseFunc(Mouse);
  glutMotionFunc(processMouseActiveMotion);

 
  srand48(time(NULL));  
  Game->Init(Game->option_materiale);
  glutMainLoop();

  return 0;             
}