#include <GL/glut.h>
#include <iostream>

using namespace std;

int main_window;
bool rotate_y = false;
GLdouble cube_center_x_on_screen, cube_center_y_on_screen, cube_center_z_on_screen;
int win_h;


double tran_z = -3;
float roty = 0;



void display(void)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glTranslatef(-tran_z * .2, 0, tran_z);
  glRotatef(roty, 0,1,0);
  glutSolidTeapot(1.0);

  
  int view[4];
  GLdouble model[16], proj[16]; 

  glGetIntegerv (GL_VIEWPORT, view);		
  glGetDoublev (GL_MODELVIEW_MATRIX, model);	
  glGetDoublev (GL_PROJECTION_MATRIX, proj);

  gluProject (0, 0, 0,
	      model, proj, view, 
	      &cube_center_x_on_screen, &cube_center_y_on_screen, &cube_center_z_on_screen);

  glutSwapBuffers(); 
}

/* Change these values for a different transformation  */
void reshape(int w, int h)
{
  win_h = h;
  
  glViewport (0, 0, (GLsizei) w, (GLsizei) h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective (90.0, (GLfloat) w/(GLfloat) h, .99, 100.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

void myGlutIdle( void )
{
  /* According to the GLUT specification, the current window is 
     undefined during an idle callback.  So we need to explicitly change
     it if necessary */
  if ( glutGetWindow() != main_window ) 
    glutSetWindow(main_window);  

  static bool move_closer = false;
  if(move_closer)
  {
    tran_z += .01;
    if(tran_z > -1.1)
      move_closer = false;
  }
  else
  {
    tran_z -= .01;
    if(tran_z < -10.0)
      move_closer = true;
  }
  
  if(rotate_y)
  {
    roty += 2;
  }

  glutPostRedisplay();
}

void mouse(int button, int state, int x, int y) 
{
  if (button == GLUT_LEFT_BUTTON) {
    if (state == GLUT_DOWN) 
    {
      if(fabs(x - cube_center_x_on_screen) < 10 && fabs( (win_h - y) - cube_center_y_on_screen) < 60)
      {
	rotate_y = !rotate_y;
      }
    }
  }
  
}
void keyboard(unsigned char key, int x, int y)
{
  if(key == 'q' || key == 'Q')
    exit(0);
}


   
/* 
 *  Open window, register input callback functions
 */
int main(int argc, char** argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

  glutInitWindowSize (500, 500); 
  glutInitWindowPosition (100, 100);
  main_window = glutCreateWindow (argv[0]);

  glutDisplayFunc(display); 
  glutReshapeFunc(reshape); 
  glutKeyboardFunc(keyboard);

  glutIdleFunc( myGlutIdle );

  glutMouseFunc(mouse);

  glClearColor(0.0, 0.1, 0.1, 0.0);
  glEnable(GL_DEPTH_TEST);
  glShadeModel(GL_SMOOTH);


  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);

  glutMainLoop();
  return 0;
}

