/*
 * ExNihilo 3D Engine
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Please read AUTHORS file !!!
 * 
 * $Id: ExNihiloNameSpace.cpp,v 1.7 2002/12/13 11:45:03 data Exp $
 *
 */

#include "ExNihiloNameSpace.h"

void ExNihilo::InitBasicObjectList(void)
{
	float i;	
	glNewList(GRILLE,GL_COMPILE);
	glDisable(GL_LIGHTING);
	glBegin(GL_LINES);
		glColor3f(1.0f,0.0f,0.0f);
		for ( i=-100;i<101;i+=2)
		{	
			glVertex3f(0.0f,      i, 100.0f);
			glVertex3f(0.0f,      i,-100.0f);
			glVertex3f(0.0f, 100.0f,      i);
			glVertex3f(0.0f,-100.0f,      i);
		}
		glColor3f(0.0,1.0f,0.0f);
		
		for ( i=-100;i<101;i+=2)
		{
			glVertex3f( 100.0f,     i,0.0f);
			glVertex3f(-100.0f,     i,0.0f);
			glVertex3f(     i, 100.0f,0.0f);
			glVertex3f(     i,-100.0f,0.0f);
		}
		glColor3f(0.0,0.0f,1.0f);
		for (i=-100;i<101;i+=2)
		{
			glVertex3f( 100.0f,0.0f,      i);
			glVertex3f(-100.0f,0.0f,      i);
			glVertex3f(      i,0.0f, 100.0f);
			glVertex3f(      i,0.0f,-100.0f);
		}
	glEnd();
	glColor3f(1.0,1.0f,1.0f);
	glEnable(GL_LIGHTING);
	glEndList();


}
void ExNihilo::DrawGrid(int size)
{
	int i;
	glDisable(GL_LIGHTING);
	glBegin(GL_LINES);
		glColor3f(1.0f,0.0f,0.0f);
		for ( i=-size;i<size+1;i+=2)
		{	
			glVertex3f(0.0f,      i, size);
			glVertex3f(0.0f,      i,-size);
			glVertex3f(0.0f, size,      i);
			glVertex3f(0.0f,-size,      i);
		}
		glColor3f(0.0,1.0f,0.0f);

		for ( i=-size;i<size+1;i+=2)
		{
			glVertex3f( size,     i,0.0f);
			glVertex3f(-size,     i,0.0f);
			glVertex3f(     i, size,0.0f);
			glVertex3f(     i,-size,0.0f);
		}
		glColor3f(0.0,0.0f,1.0f);
		for (i=-size;i<size+1;i+=2)
		{
			glVertex3f( size,0.0f,      i);
			glVertex3f(-size,0.0f,      i);
			glVertex3f(      i,0.0f, size);
			glVertex3f(      i,0.0f,-size);
		}
	glEnd();
}

void ExNihilo::ShowGlError(void)
{
	switch(glGetError())
		{
		case GL_NO_ERROR:
			std::cout<<"No Error "<<std::endl;
			break;
		case GL_INVALID_OPERATION:
			std::cout<<"Error Invalid operation "<<std::endl;
			break;
		case GL_INVALID_VALUE:
			std::cout<<"Error Invalid value "<<std::endl;
			break;
		case GL_INVALID_ENUM:
			std::cout<<"Error Invalid enum "<<std::endl;
			break;
		case GL_STACK_OVERFLOW:
			std::cout<<"Error stack overflow "<<std::endl;
			break;
		case GL_STACK_UNDERFLOW:
			std::cout<<"Error stack underflow "<<std::endl;
			break;
		case GL_OUT_OF_MEMORY:
			std::cout<<"Error out of memory"<<std::endl;
			break;
		default:
			std::cout<<"Uknow error ?"<<std::endl;
			//std::cout<<gluErrorString(glGetError())<<std::endl;
		}
		
}

int ExNihilo::GetResolutionX()
{
	return glutGet(GLUT_WINDOW_WIDTH);
}
int ExNihilo::GetResolutionY()
{
	return glutGet(GLUT_WINDOW_HEIGHT);
}

void ExNihilo::RenderBitmapString(float x, float y, void *font,std::string string)
{
	const char *c;
	glRasterPos2f(x, y);
	for (c=string.data(); *c != '\0'; c++)
	{
	   glutBitmapCharacter(font, *c);
	}
}

void ExNihilo::EnterOrthoMode(void)
{
	glPushMatrix();	
	glMatrixMode(GL_PROJECTION);						
	glPushMatrix();									
	glLoadIdentity();
	glOrtho( 0,glutGet(GLUT_WINDOW_WIDTH),glutGet(GLUT_WINDOW_HEIGHT),0,0,1);	
	glMatrixMode(GL_MODELVIEW);								
	glLoadIdentity();										
}

void ExNihilo::LeaveOrthoMode(void)	
{
	glMatrixMode( GL_PROJECTION );							
	glPopMatrix();											
	glMatrixMode( GL_MODELVIEW );							
	glPopMatrix();
}

void ExNihilo::WriteToScreen(float x,float y,std::string String)
{
	ExNihilo::EnterOrthoMode();
	ExNihilo::RenderBitmapString(x,y,(void *)GLUT_BITMAP_HELVETICA_12,String);
	ExNihilo::LeaveOrthoMode();
}

void ExNihilo::WriteToScreen(float x,float y,float r,float g,float b,std::string String)
{
	ExNihilo::EnterOrthoMode();
	glPushAttrib(GL_ALL_ATTRIB_BITS);
	glDisable(GL_LIGHTING);
	glEnable(GL_BLEND);
	glEnable(GL_ALPHA);
	glBlendFunc(GL_ONE,GL_ONE);
	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GREATER,0);
	glDisable(GL_DEPTH_TEST);
	glColor4f(r,g,b,1.0f);
	ExNihilo::RenderBitmapString(x,y,(void *)GLUT_BITMAP_HELVETICA_12,String);
	glPopAttrib();
	ExNihilo::LeaveOrthoMode();
	
}

void ExNihilo::WriteToScreen24(float x,float y,float r,float g,float b,std::string String)
{
	ExNihilo::EnterOrthoMode();
	glPushAttrib(GL_ALL_ATTRIB_BITS);
	glDisable(GL_LIGHTING);
	glEnable(GL_BLEND);
	glEnable(GL_ALPHA);
	glBlendFunc(GL_ONE,GL_ONE);
	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GREATER,0);
	glDisable(GL_DEPTH_TEST);
	glColor4f(r,g,b,1.0f);
	ExNihilo::RenderBitmapString(x,y,(void *)GLUT_BITMAP_TIMES_ROMAN_24,String);
	glPopAttrib();
	ExNihilo::LeaveOrthoMode();
	
}

void ExNihilo::DrawCadre(float x,float y,float lx,float ly,float r,float g,float b,float blend)
{
	ExNihilo::EnterOrthoMode();
	glPushAttrib(GL_ALL_ATTRIB_BITS);
	glDisable(GL_LIGHTING);
	glEnable(GL_BLEND);
	glEnable(GL_ALPHA);
	glBlendFunc(GL_ONE,GL_ONE);
	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_GREATER,0);
	glDisable(GL_DEPTH_TEST);
	glColor4f(r,g,b,blend);
	glBegin(GL_QUADS);
		glVertex2f(x,y);
		glVertex2f(x,y+ly);
		glVertex2f(x+lx,y+ly);
		glVertex2f(x+lx,y);
	glEnd();
	glDisable(GL_BLEND);
	glDisable(GL_ALPHA);
	glEnable(GL_DEPTH_TEST);
	glBegin(GL_LINE_STRIP);
		glVertex2f(x,y);
		glVertex2f(x,y+ly);
		glVertex2f(x+lx,y+ly);
		glVertex2f(x+lx,y);
		glVertex2f(x,y);
	glEnd();
	glPopAttrib();
	ExNihilo::LeaveOrthoMode();
}

std::string ExNihilo::ExtracValueFromSring(std::string buffstring,std::string start,std::string end)
{
	char buffer[255];
	memset(buffer,0,255);
	try
	{
		buffstring.copy(buffer,buffstring.find(end,buffstring.find(start)+start.size())-buffstring.find(start)-start.size(),buffstring.find(start)+start.size());
	}
	catch(...)
	{
		throw ExCExpStringNotFound();
	}
	return buffer;
}

int ExNihilo::ExtractIntValueFromSring(std::string buffstring,std::string start,std::string end)
{
	char buffer[255];
	memset(buffer,0,255);
	try{buffstring.copy(buffer,buffstring.find(end,buffstring.find(start)+start.size())-buffstring.find(start)-start.size(),buffstring.find(start)+start.size());}
	catch(...){throw ExCExpStringNotFound();}
	return atoi(buffer);
}

float ExNihilo::ExtractFloatValueFromSring(std::string buffstring,std::string start,std::string end)
{
	char buffer[255];
	memset(buffer,0,255);
	try{buffstring.copy(buffer,buffstring.find(end,buffstring.find(start)+start.size())-buffstring.find(start)-start.size(),buffstring.find(start)+start.size());}
	catch(...){throw ExCExpStringNotFound();}
	return atof(buffer);
}

std::string ExNihilo::ExtracStringValueFromFile(std::string FileName, std::string start,std::string end)
{
	char buffer[255],b[256];memset(buffer,0,255);
	std::ifstream fin;
	std::string buffstring;
	fin.open(FileName.data(),std::ios::in);
	if(fin.is_open())
	{
		try
		{
			do
			{
				memset(b,0,255);
				fin.getline(b,256,'\n');
				buffstring=buffstring+b;
			}while(!fin.eof());
			fin.close();
		}catch(...){throw ExCExpFileReadError();}
	}else throw   ExCExpFileNotFound();
	buffstring.copy(buffer,buffstring.find(end,buffstring.find(start)+start.size())-buffstring.find(start)-start.size(),buffstring.find(start)+start.size());
	return buffer;
}

int ExNihilo::ExtractIntValueFromFile(std::string FileName, std::string start,std::string end)
{
	return atoi(ExNihilo::ExtracStringValueFromFile(FileName,start,end).data());
}

float ExNihilo::ExtractFloatValueFromFile(std::string FileName, std::string start,std::string end)
{
	return atof(ExNihilo::ExtracStringValueFromFile(FileName,start,end).data());
}

int ExNihilo::ExtracStringCommandFromString(std::string FileName,std::string command,std::string &TargetString)
{
	return 1;
}

int ExNihilo::ExtracStringCommandFromFile(std::string FileName,std::string command,std::string &TargetString)
{
	char buffer[255],b[256];memset(buffer,0,255);
	std::ifstream fin;
	std::string buffstring;
	fin.open(FileName.data(),std::ios::in);
	if(fin.is_open())
	{
		try
		{
			do
			{
				memset(b,0,255);
				fin.getline(b,256,'\n');
				buffstring=buffstring+b;
			}while(!fin.eof());
			fin.close();
		}catch(...){throw ExCExpFileReadError();}
	}else throw   ExCExpFileNotFound();
//	buffstring.copy(buffer,buffstring.find(end,buffstring.find(start)+start.size())-buffstring.find(start)-start.size(),buffstring.find(start)+start.size());
	TargetString=buffer;
	return 1;
}


ExCAction ExtractActionFromString(std::string FileName,std::string command,std::string &TargetString)
{
	ExCAction RetAction;
	
	return RetAction;
}
void ExNihilo::AddKeyToBuffer(int key,std::string &buffer)
{
	switch(key)
	{
	case KEYBOARD_DOWN_A:buffer.append("a");break;
	case KEYBOARD_DOWN_Z:buffer.append("z");break;
	case KEYBOARD_DOWN_E:buffer.append("e");break;
	case KEYBOARD_DOWN_R:buffer.append("r");break;
	case KEYBOARD_DOWN_T:buffer.append("t");break;
	case KEYBOARD_DOWN_Y:buffer.append("y");break;
	case KEYBOARD_DOWN_U:buffer.append("u");break;
	case KEYBOARD_DOWN_I:buffer.append("i");break;
	case KEYBOARD_DOWN_O:buffer.append("o");break;
	case KEYBOARD_DOWN_P:buffer.append("p");break;
	case KEYBOARD_DOWN_Q:buffer.append("q");break;
	case KEYBOARD_DOWN_S:buffer.append("s");break;
	case KEYBOARD_DOWN_D:buffer.append("d");break;
	case KEYBOARD_DOWN_F:buffer.append("f");break;
	case KEYBOARD_DOWN_G:buffer.append("g");break;
	case KEYBOARD_DOWN_H:buffer.append("h");break;
	case KEYBOARD_DOWN_J:buffer.append("j");break;
	case KEYBOARD_DOWN_K:buffer.append("k");break;
	case KEYBOARD_DOWN_L:buffer.append("l");break;
	case KEYBOARD_DOWN_M:buffer.append("m");break;
	case KEYBOARD_DOWN_W:buffer.append("w");break;
	case KEYBOARD_DOWN_X:buffer.append("x");break;
	case KEYBOARD_DOWN_C:buffer.append("c");break;
	case KEYBOARD_DOWN_V:buffer.append("v");break;
	case KEYBOARD_DOWN_B:buffer.append("b");break;
	case KEYBOARD_DOWN_N:buffer.append("n");break;
	case KEYBOARD_DOWN_M_A:buffer.append("A");break;
	case KEYBOARD_DOWN_M_Z:buffer.append("Z");break;
	case KEYBOARD_DOWN_M_E:buffer.append("E");break;
	case KEYBOARD_DOWN_M_R:buffer.append("R");break;
	case KEYBOARD_DOWN_M_T:buffer.append("T");break;
	case KEYBOARD_DOWN_M_Y:buffer.append("Y");break;
	case KEYBOARD_DOWN_M_U:buffer.append("U");break;
	case KEYBOARD_DOWN_M_I:buffer.append("I");break;
	case KEYBOARD_DOWN_M_O:buffer.append("O");break;
	case KEYBOARD_DOWN_M_P:buffer.append("P");break;
	case KEYBOARD_DOWN_M_Q:buffer.append("Q");break;
	case KEYBOARD_DOWN_M_S:buffer.append("S");break;
	case KEYBOARD_DOWN_M_D:buffer.append("D");break;
	case KEYBOARD_DOWN_M_F:buffer.append("F");break;
	case KEYBOARD_DOWN_M_G:buffer.append("G");break;
	case KEYBOARD_DOWN_M_H:buffer.append("H");break;
	case KEYBOARD_DOWN_M_J:buffer.append("J");break;
	case KEYBOARD_DOWN_M_K:buffer.append("K");break;
	case KEYBOARD_DOWN_M_L:buffer.append("L");break;
	case KEYBOARD_DOWN_M_M:buffer.append("M");break;
	case KEYBOARD_DOWN_M_W:buffer.append("W");break;
	case KEYBOARD_DOWN_M_X:buffer.append("X");break;
	case KEYBOARD_DOWN_M_C:buffer.append("C");break;
	case KEYBOARD_DOWN_M_V:buffer.append("V");break;
	case KEYBOARD_DOWN_M_B:buffer.append("B");break;
	case KEYBOARD_DOWN_M_N:buffer.append("N");break;
	case KEYBOARD_DOWN_0:buffer.append("0");break;
	case KEYBOARD_DOWN_1:buffer.append("1");break;
	case KEYBOARD_DOWN_2:buffer.append("2");break;
	case KEYBOARD_DOWN_3:buffer.append("3");break;
	case KEYBOARD_DOWN_4:buffer.append("4");break;
	case KEYBOARD_DOWN_5:buffer.append("5");break;
	case KEYBOARD_DOWN_6:buffer.append("6");break;
	case KEYBOARD_DOWN_7:buffer.append("7");break;
	case KEYBOARD_DOWN_8:buffer.append("8");break;
	case KEYBOARD_DOWN_9:buffer.append("9");break;
	case KEYBOARD_DOWN__:buffer.append("_");break;
	case KEYBOARD_DOWN_2POINTS:buffer.append(":");break;
	case KEYBOARD_DOWN_POINT:buffer.append(".");break;
	case KEYBOARD_DOWN_SPACE:buffer.append(" ");break;
	case KEYBOARD_DOWN_CTRL_U:buffer = "";break;
	default :break;
	}
}

std::string ExNihilo::GetFileExtension(std::string FileName)
{
	std::string ReturnString;
	0<FileName.find(".") ? (ReturnString=FileName.substr(FileName.find(".")+1,FileName.size()-FileName.find(".")-1)) : (ReturnString="BADEXTENSION");
	return ReturnString;
}


