#include "cs148.h"

static int week = 0, day = 0, moonpos = 0;

// Functions to manipulate time
void dayAdd (void) { day = (day + 10) % 360; }
void daySubtract (void) { day = (day - 10) % 360; }

void weekAdd (void) { week = (week+ 5) % 360; }
void weekSubtract (void) { week = (week - 5) % 360; }

void moongo (void) { moonpos = (moonpos + 20) % 360; }

// Are we animating our world right now?
int animating = 0;

// If we're animating, how many milliseconds pass between animations?
#define TIMER_INTERVAL 30

void display(void) {

   // We're in 3D now, so clear the depth buffer too...
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   // Global reference frame
   glPushMatrix();

    // Draw yellow sun at the center of the universe
    glPushMatrix();
      glColor3f (1.0, 1.0, 0.0);
      glutSolidSphere(1.0, 10, 10);
    glPopMatrix();

    // Draw smaller red planet
    glPushMatrix();

      glColor3f (1.0, 0.0, 0.0);
      glRotatef ((GLfloat) week, 0.0, 1.0, 0.0);

      // The radius of his orbit is 2.0
      glTranslatef (2.0, 0.0, 0.0);

      // His day-to-day rotation won't affect his position
      glRotatef ((GLfloat) day, 0.0, 1.0, 0.0);
      glutSolidSphere(0.4, 10, 10);

      glPushMatrix();

        // Draw blue moon in the reference frame of the smaller planet
        glColor3f (0.0, 0.0, 1.0);
        glRotatef ((GLfloat) moonpos, 0.0, 1.0, 0.0);

        // The moon only needs to know how far it is from the planet,
        // not from the sun!  Hooray for transformations!
        glTranslatef (1.0, 0.0, 0.0);
        glutSolidSphere(0.2, 10, 10);

      glPopMatrix();

    glPopMatrix();

  glPopMatrix();
  glFlush();

  glutSwapBuffers();
}


// Our GLUT timer callback
void timer(int value) {

  // Move the planets along...
  dayAdd();
  weekAdd();

  // ...and register a new callback.
  if (animating) glutTimerFunc(TIMER_INTERVAL,timer,0);

  glutPostRedisplay();
}


void myinit (void) {

    // enable lighting
    float pos[4] = {0,0,2.0,0.0};
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);
    glLightfv(GL_LIGHT0,GL_POSITION,pos);
    glShadeModel (GL_SMOOTH);
  
    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);

}



void myReshape(int w, int h) {
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Set up a perspective camera
    gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef (0.0, 0.0, -5.0);
}



void myKey(unsigned char key, int x, int y) {

  switch (key) {
    case 'w': {
      weekAdd();
      break; }
    case 'W': {
      weekSubtract();
      break; }
    case 'd': {
      dayAdd();
      break; }
    case 'D': {
      daySubtract();
      break; }
    case 'm': {
      moongo();
      break; }
    case 'a': {
      animating = 1 - animating;
      if (animating) glutTimerFunc(TIMER_INTERVAL,timer,0);
    }
  }
  glutPostRedisplay();
}


/*  Main Loop
 *  Open window with initial window size, title bar, 
 *  RGBA display mode, and handle input events.
 */
int main(int argc, char** argv) {
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
   glutInitWindowSize (500, 500); 
   glutInitWindowPosition (100, 50);
   glutCreateWindow (argv[0]);
   myinit ();
   glutKeyboardFunc(myKey);
   glutDisplayFunc(display); 
   glutReshapeFunc(myReshape);
   glutMainLoop();
   return 0;
}


