#pragma once

#include <windows.h>
#include <stdlib.h>
#include <io.h>
#include <iostream>
#include <stdio.h>
#include <fstream>
#include <string.h>
#include <glew.h>
#include <math.h>
#include <GL/glut.h>
using namespace std;

#include "Timer.h"
static Timer* timer;
#include "Camera.h"
static Camera* camera;

static int windowWidth = 800;
static int windowHeight = 600;
static GLfloat light_position[] = { 12.0f, 12.0f, -12.0f, 0.0f };

/**
 * Amount of time since the last frame
 */
static float getTimeSinceLastFrame()
{
	return timer->getSecondsPassed();
}

/**
 * Load the content of a textfile and return it as a string
 */
std::string loadTextFile(char* filename)
{
	std::string storage;
	std::ifstream file;
	file.open(filename, std::ios::in);
	if(!file) return storage;

	while (file.good())
	{
		char c = file.get();
		if( (unsigned int)c < 255 )
			storage += c;
	}
	return storage;
}

/**
 * Set the actual light position
 */
static void setLightPos()
{
	glLightfv(GL_LIGHT0, GL_POSITION, light_position);
}

/**
 * Render the actual light position
 */
static void renderLightPos()
{
	glColor3f(1, 1, 0.5);
	glPushMatrix();
		glTranslatef(light_position[0], light_position[1], light_position[2]);
		glutSolidSphere(1, 20, 20);
	glPopMatrix();
}

/**
 * Update stuff for a new frame (e.g. the timer)
 */
static void newFrame()
{
	timer->LoadNewTime();
}

/**
 * Set the actual camera position for rendering
 */
static void setCamera()
{
	camera->render();
}

/**
 * Display a simple text s at position (x,y)
 */
static void glSimpleText(int x, int y, char* s)
{
	int lines;
	char* p;

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glOrtho(0.0, glutGet(GLUT_WINDOW_WIDTH), 0.0, glutGet(GLUT_WINDOW_HEIGHT), -1.0, 1.0);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glRasterPos2i(x, y);
	for(p = s, lines = 0; *p; p++) {
		if (*p == '\n') {
			lines++;
			glRasterPos2i(x, y-(lines*18));
		}
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
	}
	glPopMatrix();
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
}

/**
 * Render the help text to show the user how to control the application
 */
static void renderHelpText()
{
	glSimpleText(20, 50, "ESC ..... End program");
	glSimpleText(20, 80, "mouse ... Rotate camera");
}

/**
 * Render the current frames per second
 */
static void renderFPS()
{
	static int i=0;
	static float times[10];
	times[i]=timer->getSecondsPassed();
	char buffer [50];
	int n;
	float fps = 10.0f/(times[0]+times[1]+times[2]+times[3]+times[4]+
		times[5]+times[6]+times[7]+times[8]+times[9]);
	n=sprintf (buffer, "%.2f fps", fps);

	glColor3f(0.2, 0.2, 1);
	glSimpleText(20, 20, buffer);

	i++;
	i%=10;
}

/**
 * Rotate the camera in x/y dir
 */
static void rotateCamera(float x, float y)
{
	camera->rotateX(x * 3.1415 / 180.0);
	camera->rotateY(y * 3.1415 / 180.0);
}

/**
 * Initiate the window and other stuff needed for rendering
 */
static void init(int argc, char* argv[])
{
	timer = new Timer();
	timer->LoadStartTime();

	camera = new Camera();

	glViewport(0, 0, windowWidth, windowHeight);
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f,(GLfloat)windowWidth/(GLfloat)windowHeight,0.1f,1000.0f);
	glMatrixMode(GL_MODELVIEW);



	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glFrontFace(GL_CCW);
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);
	glClearColor(0, 0, 0, 1);
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	GLfloat ambientLight[] = { 0.1f, 0.1f, 0.1f, 1.0f };
	GLfloat diffuseLight[] = { 0.9f, 0.9f, 0.9f, 1.0f };
	glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
	glEnable(GL_COLOR_MATERIAL);
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
}