
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "surface.h"
#include "wrapglut.h"
#include "include/bass.h"

//bool paused;
int rendering;
int window;
int screenx,screeny;
int mousex,mousey,mouseb,mouses;
int mouseox,mouseoy;
float frames;
GLuint texture[200];

///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////                 initGL                ////////////////////
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////


int initGL(unsigned int mode,int width,int height,int x,int y,char *title,char fullscreen)
{
	int maxtexturesize;
	glutInitDisplayMode(mode);
	glutInitWindowSize(width,height);
	glutInitWindowPosition(x,y);  
	if (fullscreen)
	{
		glutGameModeString("640x480:32");
		glutEnterGameMode();
	}
	else window=glutCreateWindow(title);

	//if (fullscreen) glutFullScreen();
	printf("--GFX Init--\n");
	printf("Vendor    - %s\n",glGetString(GL_VENDOR));
	printf("Renderer  - %s ver%s\n",glGetString(GL_RENDERER),glGetString(GL_VERSION));
	printf("Texture   - "); glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxtexturesize); printf("%ix%i\n",maxtexturesize,maxtexturesize);
	printf("Buffer    - %ibpp\n",glutGet(GLUT_WINDOW_BUFFER_SIZE));
	printf("Z-Buffer  - %ibpp\n",glutGet(GLUT_WINDOW_DEPTH_SIZE));
	return 1;
}

///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////              initGLTweaks             ////////////////////
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////


void initGLTweaks()
{
	glShadeModel(GL_SMOOTH);						// Enable Smooth Shading
	glClearColor(0.0f,0.0f,0.0f,1.0f);					// Black Background
	glClearDepth(1.0f);							// Depth Buffer Setup
	glEnable(GL_DEPTH_TEST);						// Enables Depth Testing
	glDepthFunc(GL_LEQUAL);							// The Type Of Depth Testing To Do
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// Really Nice Perspective Calculations
	//glBlendFunc(GL_ONE_MINUS_DST_ALPHA,GL_ZERO);
	//glBlendFunc(GL_SRC_ALPHA,GL_DST_ALPHA);
    //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE);

	glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_DEPTH_BUFFER_BIT);
	glutSwapBuffers();
	glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_DEPTH_BUFFER_BIT);
	glutSwapBuffers();
	glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_DEPTH_BUFFER_BIT);

	glEnable(GL_DEPTH_TEST);
	glEnable(GL_DITHER);

	//glEnable(GL_LIGHTING);
	//glEnable(GL_LIGHT0);
	//glEnable(GL_LIGHT1);
}


///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////                Reshape                ////////////////////
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

void Reshape(int width, int height)
{
	screenx=width;
	screeny=height;
	glViewport(0,0,width,height);						// Reset The Current Viewport
	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
	glLoadIdentity();									// Reset The Projection Matrix
	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,350.0f);
//	glOrtho(-50, 50, -50, 50.0f, 0.1f, 250.0f);
	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
	glLoadIdentity();	
}

///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////                 update                ////////////////////
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

void update(int value)
{
  if (rendering) return;
  glutPostRedisplay();
  glutTimerFunc(5, update, 0);
}

///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////                  Key                  ////////////////////
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

void Key(unsigned char key, int x, int y)
{
	//ESC
    if (key==27) 
    { 
		BASS_Stop();
		BASS_Free();
		if (window!=0) { glutDestroyWindow(window); exit(0); }
		else glutLeaveGameMode();
	exit(0);                   
    }
	//P
	if (key==112)
		paused=!paused;
}

unsigned int GetFreeTextureIndex()
{
	unsigned int index;
	//glDeleteTextures(1, &index);
	glGenTextures(1, &index);					
	//printf("ID: %i\n",index);
	return index;
}

void MapTexture(GLuint index,CSurface *s)
{
	glBindTexture(GL_TEXTURE_2D, index);

	if (s->channels==4)
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, s->xdim,s->ydim, 0, GL_RGBA, GL_UNSIGNED_BYTE,s->data);
	if (s->channels==3)
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, s->xdim,s->ydim, 0, GL_RGB, GL_UNSIGNED_BYTE,s->data);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
	//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);

	/*glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST);

	if (s->channels==4)
		gluBuild2DMipmaps(GL_TEXTURE_2D, 4, s->xdim,s->ydim,GL_RGBA,GL_UNSIGNED_BYTE,s->data);
	if (s->channels==3)
		gluBuild2DMipmaps(GL_TEXTURE_2D, 3, s->xdim,s->ydim,GL_RGB,GL_UNSIGNED_BYTE,s->data);
*/
}



void textwrite(int x, int y, char *string,float r,float g,float b)
{
  int len, i;
  unsigned char lightstat,tmapstat;
  void *font = GLUT_BITMAP_9_BY_15;

  glViewport(0, 0, screenx,screeny);
  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  gluOrtho2D(0, screenx, screeny, 0);
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();

  lightstat=glIsEnabled(GL_LIGHTING);
  tmapstat=glIsEnabled(GL_TEXTURE_2D);
  glDisable(GL_LIGHTING);
  glDisable(GL_TEXTURE_2D);
  glColor3f(r,g,b);
  glRasterPos2f(x, y);
  len = (int) strlen(string);
  for (i = 0; i < len; i++) {
    glutBitmapCharacter(font, string[i]);
  }

  glPopMatrix();
  glMatrixMode(GL_PROJECTION);
  glPopMatrix();

  if (lightstat) glEnable(GL_LIGHTING);
  if (tmapstat) glEnable(GL_TEXTURE_2D);
}


void screenClear(float percent,int buffers)
{
	//glClearColor(0.1f,0.2f,0.4f,1.0f);
	glClear(buffers);
	if (percent>=1.0) 
	{
		glClear(GL_COLOR_BUFFER_BIT);
	}
	else
	{
		glDisable(GL_DEPTH_TEST);
		glDisable(GL_LIGHTING);
		glDisable(GL_CULL_FACE);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glEnable(GL_BLEND);
		glDisable(GL_TEXTURE_2D);
		/*
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0,0,-1);
		glBegin(GL_QUADS);
			glColor4f(0.0, 0.0, 0.0, percent);
			glVertex3f(-1,-1,0);
			glVertex3f(1,-1,0);
			glVertex3f(1,1,0);
			glVertex3f(-1,1,0);
		glEnd();*/

		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glLoadIdentity ();
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		glLoadIdentity();

		glBegin (GL_QUADS);
			glColor4f(0,0,0,percent);
			glVertex3f (-1, -1, 0);
			glVertex3f ( 1, -1, 0);
			glVertex3f ( 1,  1, 0);
			glVertex3f (-1,  1, 0);
		glEnd ();

		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
		glPopMatrix();

		glEnable(GL_DEPTH_TEST);
		glDisable(GL_BLEND);
		glEnable(GL_CULL_FACE);
	}
}

///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////