#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include "shape.h"

/* you may need to locate glut.h on your computer and change the path accordingly
 It is most likely in ~/include or ~include/GL.
 */

/* the viewport is 500x500 with the origin at (0,0) */
int Vx_min=0, Vx_max=500, Vy_min=0, Vy_max=500, Vz_min=0, Vz_max=0;

void cross_product(float u[3], const float v[3], const float w[3]) {

  u[0] = v[1]*w[2] - v[2]*w[1];
  u[1] = v[2]*w[0] - v[0]*w[2];
  u[2] = v[0]*w[1] - v[1]*w[0];

}

void init(void) 
{   
   GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat mat_shininess[] = { 50.0 };
   GLfloat light_position[] = { -10.0, 10.0, -10.0, 1.0 };
   GLfloat light1_position[] = { 0.5, 0.5, 0.5, 0.5 };
   GLfloat light1_color[] = { 0.0, 0.0, 1.0, 1.0 };
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glShadeModel (GL_SMOOTH);

   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
   glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
   glLightfv(GL_LIGHT1,	GL_AMBIENT, light1_position);
   glLightfv(GL_LIGHT1,	GL_AMBIENT, light1_color);

   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glEnable(GL_LIGHT1);
   glEnable(GL_DEPTH_TEST);

   /* do we need this? */
    glEnable(GL_NORMALIZE);

}

Shape shape;
Shape shape2;
float **normals;
int *didIt;

void display(void)
{
	int i;
	float edge1[3];
	float edge2[3];
	float tri_normal[3];

	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity ();             /* clear the matrix */
	  /* viewing transformation  */
	/* torus LookAt */
	gluLookAt (3.0, 8.0,4.0, 0.0, 0.0, 2.0, 0.0, 1.0, 0.0);
	/* lshape LookAt */
	//gluLookAt (-3.0, -3.0,5.0, 0.0, 0.0, 2.0, 0.0, 1.0, 0.0);
	/* cube LookAt */
	//gluLookAt (5.0, 5.0,5.0, 0.0, 0.0, 2.0, 0.0, 1.0, 0.0);
	/* tetrahedron LookAt */
	//gluLookAt (-2.5, -0.75, -0.1, 0.0, 0.0, 2.0, 0.0, 1.0, 0.0);

	glScalef (1.0, 2.0, 1.0);      /* modeling transformation */

	/* testing a 3d shape */
	//glutSolidSphere(1.0,20,16);

	if(shape!=NULL)
	{
	    /* green */
	    glColor3f(0.0,1.0,0.0); /* params are floats in range [0.0,1.0] */
	    for(i=0;i<numTriangles(shape);i++)
	      {
		glBegin(GL_POLYGON);
		/* assign normal */
		glNormal3fv(normals[shape->tTable[i*3]]);
		glVertex3f(shape->vTable[3*shape->tTable[i*3]],
			   shape->vTable[3*shape->tTable[i*3]+1],
			   shape->vTable[3*shape->tTable[i*3]+2]);

		glNormal3fv(normals[shape->tTable[i*3+1]]);
		glVertex3f(shape->vTable[3*shape->tTable[i*3+1]],
			   shape->vTable[3*shape->tTable[i*3+1]+1],
			   shape->vTable[3*shape->tTable[i*3+1]+2]);

		glNormal3fv(normals[shape->tTable[i*3+2]]);
		glVertex3f(shape->vTable[3*shape->tTable[i*3+2]],
			   shape->vTable[3*shape->tTable[i*3+2]+1],
			   shape->vTable[3*shape->tTable[i*3+2]+2]);
		glEnd();
		glFlush();
	      }
	}
	if(shape2 != NULL)
	  {
	    glColor3f(1.0,0.0,0.0);
	    for(i=0;i<numTriangles(shape2);i++)
	      {
		glBegin(GL_LINE_STRIP);
		glVertex3f(shape2->vTable[3*shape2->tTable[i*3]],
			   shape2->vTable[3*shape2->tTable[i*3]+1],
			   shape2->vTable[3*shape2->tTable[i*3]+2]);
		glVertex3f(shape2->vTable[3*shape2->tTable[i*3+1]],
			   shape2->vTable[3*shape2->tTable[i*3+1]+1],
			   shape2->vTable[3*shape2->tTable[i*3+1]+2]);
		glVertex3f(shape2->vTable[3*shape2->tTable[i*3+2]],
			   shape2->vTable[3*shape2->tTable[i*3+2]+1],
			   shape2->vTable[3*shape2->tTable[i*3+2]+2]);
		glVertex3f(shape2->vTable[3*shape2->tTable[i*3]],
			   shape2->vTable[3*shape2->tTable[i*3]+1],
			   shape2->vTable[3*shape2->tTable[i*3]+2]);
		glEnd();
		glFlush();
		sleep(3);
	      }
	  }
	glFlush ();
}

void reshape (int w, int h)
{
   
   glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   /* 2d views */
   //gluOrtho2D(Vx_min, Vx_max, Vy_min, Vy_max);
   //glOrtho(-500.0, 500.0, -500.0, 500.0, -500.0, 500.0);
   /* 3d views */
   gluPerspective(90, 1, 1, 1000);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity ();
}
void mouse(int button, int state, int x, int y)
{
/*   switch (button) {
      case GLUT_LEFT_BUTTON:
		  if (state == GLUT_DOWN) {
			printf("left mouse click\n");
			glutPostRedisplay();
		  }
         break;
      default:
         break;
   }*/
}

int main(int argc, char** argv)
{
   int c,i;
   float v[3], w[3];
   float *vTable;

   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
   glutInitWindowSize (Vx_max-Vx_min, Vy_max-Vy_min); 
   glutInitWindowPosition (100, 100);
   glutCreateWindow (argv[0]);
   
   if(argc > 3)
   {
	printf("Usage: %s fileName\n",argv[0]);
 	return 1;
   } 
   if(argc > 1)
   	shape = readShapeFromFile(argv[1]);
   if(argc > 2)
	shape2 = readShapeFromFile(argv[2]);

   if(shape != NULL)
   {
	printf("We have %d vertices.\n",shape->numVertices); 
	normals = malloc(sizeof(float*)*shape->numVertices);
	for(c=0;c<shape->numVertices;c++)
	{
		normals[c]=malloc(sizeof(float)*3);
		normals[c][0] = normals[c][1] = normals[c][2] = 0;
		for(i=0;i<numTriangles(shape);i++)
		{
			vTable = shape->vTable;
			if(c == shape->tTable[i*3])
			{
			v[0]=vTable[shape->tTable[i*3 +1]*3] - vTable[shape->tTable[i*3]*3];
			v[1]=vTable[shape->tTable[i*3 +1]*3+1]-vTable[shape->tTable[i*3]*3+1];
			v[2]=vTable[shape->tTable[i*3 +1]*3+2]-vTable[shape->tTable[i*3]*3+2];

			w[0]=vTable[shape->tTable[i*3 +2]*3] - vTable[shape->tTable[i*3]*3];
			w[1]=vTable[shape->tTable[i*3 +2]*3+1]-vTable[shape->tTable[i*3]*3+1];
			w[2]=vTable[shape->tTable[i*3 +2]*3+2]-vTable[shape->tTable[i*3]*3+2];

  			normals[c][0] += v[1]*w[2] - v[2]*w[1];
  			normals[c][1] += v[2]*w[0] - v[0]*w[2];
  			normals[c][2] += v[0]*w[1] - v[1]*w[0];
			}
			else if (c == shape->tTable[i*3 +1])
			{
			v[0]=vTable[shape->tTable[i*3 +2]*3] - vTable[shape->tTable[i*3+1]*3];
			v[1]=vTable[shape->tTable[i*3 +2]*3+1]-vTable[shape->tTable[i*3+1]*3+1];
			v[2]=vTable[shape->tTable[i*3 +2]*3+2]-vTable[shape->tTable[i*3+1]*3+2];

			w[0]=vTable[shape->tTable[i*3]*3] - vTable[shape->tTable[i*3+1]*3];
			w[1]=vTable[shape->tTable[i*3]*3+1]-vTable[shape->tTable[i*3+1]*3+1];
			w[2]=vTable[shape->tTable[i*3]*3+2]-vTable[shape->tTable[i*3+1]*3+2];

  			normals[c][0] += v[1]*w[2] - v[2]*w[1];
  			normals[c][1] += v[2]*w[0] - v[0]*w[2];
  			normals[c][2] += v[0]*w[1] - v[1]*w[0];
			}
			else if (c == shape->tTable[i*3 + 2])
			{
			v[0]=vTable[shape->tTable[i*3 ]*3] - vTable[shape->tTable[i*3+2]*3];
			v[1]=vTable[shape->tTable[i*3 ]*3+1]-vTable[shape->tTable[i*3+2]*3+1];
			v[2]=vTable[shape->tTable[i*3 ]*3+2]-vTable[shape->tTable[i*3+2]*3+2];

			w[0]=vTable[shape->tTable[i*3 +1]*3] - vTable[shape->tTable[i*3+2]*3];
			w[1]=vTable[shape->tTable[i*3 +1]*3+1]-vTable[shape->tTable[i*3+2]*3+1];
			w[2]=vTable[shape->tTable[i*3 +1]*3+2]-vTable[shape->tTable[i*3+2]*3+2];

  			normals[c][0] += v[1]*w[2] - v[2]*w[1];
  			normals[c][1] += v[2]*w[0] - v[0]*w[2];
  			normals[c][2] += v[0]*w[1] - v[1]*w[0];
			}
		}
	}
   }

   init ();

   glutDisplayFunc(display); 
   glutReshapeFunc(reshape);
   glutMouseFunc(mouse);
   glutMainLoop();
   return 0;
}
