

#include <iostream>
#include <math.h>
#include <string>

#include <GL/glut.h>
#include <ctime>
#include "geometry.h"
#include "grid.h"


using namespace std;


// function prototypes
void display(void);
void reshape(int width, int height);
void motion(int x, int y);
void init(void);
void keyboard(unsigned char key, int mouseX, int mouseY);
void idle();


// window
int width=400;
int height=400;


// view position, angles are in degrees
float phi=0;
float theta=0;
float radius=500;

bool  animate=false;
enum displayModes {  // not sure what these will be yet, but will include velocity, pressure
	CELLS = 0
};
int currDisplay = CELLS;



// the grid

Grid theGrid;

		

int 
main(int argc, char **argv)
{

	// set up window
	glutInitWindowSize(width,height);
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutCreateWindow("Fluid Simulation");

	// register callback functions
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutMotionFunc(motion);
	glutKeyboardFunc(keyboard);


	// initalize opengl parameters
	init();

	// loop until something happens
	glutMainLoop();
	return 0;           
}


void init()
{
  // initialize viewing system
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0, 1.0, 1.0, 1000.0);
  glMatrixMode(GL_MODELVIEW);
 

  // initialize background color to black
  glClearColor(0.0,0.0,1.0,0.0);

  // enable depth buffering
  glEnable(GL_DEPTH_TEST);



 
}


void reshape(int newWidth, int newHeight)
{

	width = newWidth;
	height = newHeight;
	// preserve aspect ratio
	if (width < height)
		glViewport(0,0,width,width);
	else
		glViewport(0,0,height,height);
}

void display()
{

	
	// clear buffers
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// compute eye position
	glLoadIdentity();

	
	float eye[3];
	float rtheta = theta*3.14159/180.0;
	float rphi = phi*3.14159/180.0;
	eye[0] = (float) radius * cos(rtheta) * sin(rphi);
	eye[1] = (float) radius * sin(rtheta);
	eye[2] = (float) radius * cos(rtheta) * cos(rphi);

	// compute up vector
	// toward is -eye
	float up[3];
	up[0] = -sin(rtheta)*sin(rphi);
	up[1] = cos(rtheta);
	up[2] = -sin(rtheta)*cos(rphi);
	
	// set viewpoint
	gluLookAt(eye[0],eye[1],eye[2], 0,0,0,up[0], up[1], up[2]);



	// draw grid
	glPushMatrix();
	glScalef(10,10,10);
	theGrid.draw();
	glPopMatrix();

	glutSwapBuffers();


}
void motion(int x, int y)
{

	static int currX=-1;
	static int currY=-1;

	if (animate==true)
		return;

	if (currX>0  && abs(x-currX) < width/6 && abs(y-currY) < height/6) {
		phi -= (double) (x-currX)/ (double) width * 90;
		theta += (double) (y-currY)/ (double) height * 90;

	}

	// restrict theta to be between -75 and 75
	if (theta < -60)
		theta = -60;
	if (theta > 60)
		theta = 60;

	currX = x;
	currY = y;
	glutPostRedisplay();
}

void keyboard(unsigned char key, int mouseX, int mouseY)
{ 

	switch (key){

	case 'r':
		radius -= 1.0f;
		if (radius < 0.5)
			radius = 0.5;
		break;

	case 'R':
		radius += 1.0f;
		break;

	case 'a':
	case 'A':
		if (animate == true) {
			glutIdleFunc(NULL);
			animate=false;
			cout << "Animation off." << endl;
		}
		else {
			glutIdleFunc(idle);
			animate=true;
			cout << "Animation on." << endl;
		}

		break;

	case 'i':
	case 'I':
		animate=false;
		glutIdleFunc(NULL);
//		g.reInit();
		cout << "Cell system initalized." << endl;
		glutPostRedisplay();

		break;

	case '+':
		for (int i=0;i<10; i++)
//			g.update();
		break;



	default:
		break;
	}


	glutPostRedisplay();

}




void idle() {


	static clock_t curr=0; 

	
	if (curr==0)
		curr = clock();
//	g.update();

	double d;
	while (d=(clock()-curr)/(double)CLOCKS_PER_SEC < 1/30.0)
		{};

	curr=clock();

	glutPostRedisplay();

	
}

