#include "cs148.h"

float cuberotx=0.0,cuberoty=45.0;

// Options the user can turn on or off
int perspective = 1;
int depth_testing = 1;
int clear_color_buffer = 1;
int clear_depth_buffer = 1;

int winw,winh;

float camera_x=0.0, camera_z=3.0;

void lights(void);

void display(void)
{

   // Clear the frame buffer if the user wants us to
   if (clear_color_buffer) glClear(GL_COLOR_BUFFER_BIT);

   // Clear the depth buffer if the user wants us to
   if (clear_depth_buffer) glClear(GL_DEPTH_BUFFER_BIT);

   // Set up our projection matrix.  Normally this doesn't happen
   // every frame, but since we change it around in this program,
   // it's helpful to do it here in the display() function
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
  
   // Set up a perspective or orthographic projection
   if (perspective) gluPerspective(45.0,1.0,1.5,20.0);
   else glOrtho(-1.5,1.5,-1.5,1.5,1.5,20.0);

   // Back to modelview mode
   glMatrixMode (GL_MODELVIEW);
   glLoadIdentity ();          

   // Place the camera (really this translates everything else by
   // the opposite of (camera_x,0,camera_z) )
   gluLookAt(camera_x, 0.0, camera_z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

   // Turn on the lights... we position lights in _world_ space,
   // so we have to do it _after_ the camera transformation
   lights();

   // Rotate the cube if the user asked us to
   glRotatef(cuberotx,1,0,0);
   glRotatef(cuberoty,0,1,0);

   // Turn depth testing on or off, depending on what the user
   // wants to see...
   if (depth_testing) glEnable(GL_DEPTH_TEST);
   else glDisable(GL_DEPTH_TEST);

   glColor3f (0.5, 1.0, 1.0);
   //glutWireTeapot(1.0);
   glutSolidCube(1.0);

   glutSwapBuffers();
}


void reshape (int w, int h)
{
   winw = w; winh = h;
   glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
}


void keyboard(unsigned char key, int x, int y)
{

  switch (key) {
    case 'a':
      cuberotx+=5.0;
      break;
    case 'z':
      cuberotx-=5.0;
      break;
    case 's':
      cuberoty+=5.0;
      break;
    case 'x':
      cuberoty-=5.0;
      break;
    case 'd':
      depth_testing = 1 - depth_testing;
      break;
    case 'c':
      clear_color_buffer = 1 - clear_color_buffer;
      break;
    case 'f':
      clear_depth_buffer = 1 - clear_depth_buffer;
      break;
    case 'p':
      perspective = 1 - perspective;
      break;
    case 'i':
      camera_z -= 0.2;
      break;
    case 'k':
      camera_z += 0.2;
      break;
    case 'l':
      camera_x += 0.2;
      break;
    case 'j':
      camera_x -= 0.2;
      break;
    
  }
  glutPostRedisplay();
}


void init(void) 
{
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glEnable(GL_DEPTH_TEST);
   glShadeModel(GL_SMOOTH);
   glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
   glEnable(GL_COLOR_MATERIAL);
}


// Turn the light on
void lights(void)
{

  // The position of the light
  GLfloat position[] =  {3.0, 3.0, 3.0, 1.0};

  GLfloat color[] = {0.5,0.5,0.5,1};
  GLfloat acolor[] = {0.4,0.4,0.4,1};
  
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  
  glLightfv(GL_LIGHT0, GL_POSITION, position);
  glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 80.0);
  glLightfv(GL_LIGHT0, GL_AMBIENT, acolor);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, color);
  glLightfv(GL_LIGHT0, GL_SPECULAR, color);

}


int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize (500, 500); 
   glutInitWindowPosition (100, 100);
   glutCreateWindow (argv[0]);
   glutKeyboardFunc(keyboard);
   init ();
   glutDisplayFunc(display); 
   glutReshapeFunc(reshape);
   glutMainLoop();
   return 0;
}

