//******************************************************************************
//* Christopher A. Robbins                                                     *
//* Graphics:  Assignment Three                                                *
//* November 5, 2001                                                           *
//******************************************************************************
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <gl/glut.h>
#include <iostream.h>
#include <time.h>
#include <math.h>
#include "cvec3t-vc.h"
#include "cmat3t-vc.h"
#include "transforms.h"
#include "Assignment3.h"

// Global Vectors for Maintaining Table Center and Camera Position
CVec3T<float> tableCenter(-0.25, 1.5, -0.3);
CVec3T<float> cameraPosition(-4.0, 3.0, 4.0);

// Global Unit Vector for Zooming Camera To and From Table Center
CVec3T<float> cameraZoom;

// Global Class for Maintaining Currenct User Selected Action
action globalAction;

// Standard Reshape Function
void  Reshape(int width, int height) {

  glViewport(0,0,width,height);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(60.0, (GLfloat) width/(GLfloat) height, 0.2, 20.0);

}

void Draw() {


   glClearColor( 0.0, 0.0,0.0,0.0);
   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   
   // Process camera location and direction
   look_at(cameraPosition, tableCenter);

   // Process changes due to user selected action
   globalAction.processAction(cameraPosition, tableCenter, cameraZoom);

   // Draw Scene
   glPushMatrix(); //World

		glPushMatrix(); //Floor
			translate(0.0, -1.0, 0.0);
			drawCube(8.0, 0.0, 6.0);
		glPopMatrix();

		glPushMatrix(); //Table
			translate(-0.25, 0.0, -0.5);
			drawTable();
		glPopMatrix();

		glPushMatrix(); // BackChair
			translate(0.0, 0.0, -2.25);
			drawChair();
		glPopMatrix();

		glPushMatrix(); // RightChair
			translate(globalAction.RightChairX, 0.0,  -0.5);
			rotate(-90.0, 0.0, 1.0, 0.0);
			drawChair();
		glPopMatrix();

		glPushMatrix(); // FrontChair
			translate(1.0, 0.0, 2.0);
			rotate(210.0, 0.0, 1.0, 0.0);
			drawChair();
		glPopMatrix();

	glPopMatrix();
  
	/* once we are done   drawing we swap the back and front buffers */
	glutSwapBuffers();
}

/* callback for button clicks; gets called each time a mouse button is pressed or released */
/* this function does nothing; we can start and stop animation if we call 
  glutIdleFunc() in the right place here; to disable idel callback, call glutIdleFunc(0) 
 */

void Mouse( int button, int state, int x, int y) {
  if( button == GLUT_LEFT_BUTTON ) {
    if( state == GLUT_UP ) {
		//if left button clicked swap action state
		globalAction.swapActionState();
    } else if (state == GLUT_DOWN) {     
    } else {
      assert(0);
    }
  } else if( button == GLUT_MIDDLE_BUTTON ) {

  } else if( button == GLUT_RIGHT_BUTTON) {
    if( state == GLUT_UP ) {
    } else if (state == GLUT_DOWN) {
    } else {
      assert(0);
    }

  } else {
     assert(0);
  }
}

// Simple Menu Handler
void menuHandler(int value) {

	// Set current user selected action to value passed in from pop-up menu
	// selection
	globalAction.actionSelected = value;
	cameraZoom = tableCenter - cameraPosition;
	cameraZoom = cameraZoom.dir()/100;

}



int main(int argc, char* argv[]) {


   /* initialize glut and parse command-line aguments that glut understands */
   glutInit(&argc, argv);

   /* initialize dislay mode: 4 color components, double buffer and depth buffer */
   glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);

   glutInitWindowSize(800,600);
   glutCreateWindow("Assignment 3");
// glutFullScreen();

  /* register all callbacks */

   glutDisplayFunc(Draw);
   /* this registers an "idle" callback, that is, a function that gets 
      called when there are no events to process on the queue; 
      we use Draw() but it can be a different function */
   glutIdleFunc(Draw);

   glutReshapeFunc(Reshape);
   glutMouseFunc(Mouse);

   // Create pop-up menus
   int mainMenuId = glutCreateMenu(menuHandler);
	glutAttachMenu(GLUT_RIGHT_BUTTON);
	glutSetMenu(mainMenuId);

	glutCreateMenu(menuHandler);
		glutAddMenuEntry("Fly to Table Center",        1);
		glutAddMenuEntry("Fly Away from Table Center", 2);
		glutAddMenuEntry("Fly Around Table Center",    3);
		glutAddMenuEntry("Move Chair To Table",        4);
		glutAddMenuEntry("Move Chair Away From Table", 5);

	glutCreateMenu(menuHandler);
		glutAddMenuEntry("Rotate about X-axis",6);
		glutAddMenuEntry("Rotate about Y-axis",7);
		glutAddMenuEntry("Rotate about Z-axis",8);


	glutSetMenu(mainMenuId);
	glutAddSubMenu("Project Commands", 2);
	glutAddSubMenu("Debugging",   3);
	glutAttachMenu(GLUT_RIGHT_BUTTON);
	
   // Place lights as specified in Homework3 directions
   GLfloat diffuse[] =      { 0.8, 0.8, 0.8, 1.0};

	GLfloat lgt1_diffuse[] = { 0.05f, 0.05f,  0.6f, 1.0f };
	GLfloat lgt2_diffuse[] = { 0.6f,  0.05f, 0.05f, 1.0f };

	GLfloat light_pos1[] =   { 5.0f, 5.0f, 0.0f, 1.0f };
	GLfloat light_pos2[] =   {-5.0f, 5.0f, 0.0f, 1.0f };

	glEnable(GL_LIGHTING);
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_LIGHTING);

	glMaterialfv( GL_FRONT, GL_DIFFUSE, diffuse);

	glLightfv(GL_LIGHT1, GL_POSITION,light_pos1);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, lgt1_diffuse);
	glLightfv(GL_LIGHT2, GL_POSITION,light_pos2);
	glLightfv(GL_LIGHT2, GL_DIFFUSE, lgt2_diffuse);

	glEnable(GL_LIGHT1);
	glEnable(GL_LIGHT2);

   /* this is an infinte loop get event - dispatch event which never returns */
   glutMainLoop();
   return 0;
}
