#include "global.h"
//#include "wingdi.h"
//#pragma comment(lib,"gdi32.lib")



/*
  This code is based heavily off of NeHe's Tutorials, #14.

  The code was made a little more flexible and I also included
  some error checking (always a good thing).
*/
GLFont::GLFont(char* fname, char *filename, float depth, bool lineOnly, bool bitmapped)
{
	int format;												// wgl font format
	HFONT	font;												// Windows Font ID
	BOOL ret;												// return value for error checking
	//int ret2;												// Another return value for error checking
	HGDIOBJ oldsel;										// for error checking & unselection

	baseDList = glGenLists(256);						// Storage For 256 Characters

	if (filename)	
	{
		//ret = AddFontResourceEx(filename,0,0);
		ret = AddFontResource(filename);
		if (ret != 1)
		{
			isvalid = false;
			printf("GLFont: Could not load font file \"%s\"\n",filename);
			return;
		}
	}


	font = CreateFont(	-depth,						// Height Of Font (doesn't matter for outline, use depth for bitmapped)
						0,										// Width Of Font
						0,										// Angle Of Escapement
						0,										// Orientation Angle
						FW_BOLD,								// Font Weight
						FALSE,								// Italic
						FALSE,								// Underline
						FALSE,								// Strikeout
						ANSI_CHARSET,						// Character Set Identifier
						OUT_TT_PRECIS,						// Output Precision
						CLIP_DEFAULT_PRECIS,				// Clipping Precision
						ANTIALIASED_QUALITY,				// Output Quality
						FF_DONTCARE|DEFAULT_PITCH,		// Family And Pitch
						fname);								// Font Name

	if (font == NULL)
	{
		isvalid = false;
		printf("GLFont: Could not access font named \"%s\"\n",fname);
		return;
	}

	oldsel = SelectObject(glutarConfig.hDC, font);	// Selects The Font We Created

	if (oldsel == NULL || oldsel == HGDI_ERROR)
	{
		isvalid = false;
		printf("GLFont: Could not select loaded font named \"%s\"\n",fname);
		return;
	}

	isbitmap = bitmapped;

	if (bitmapped)
	{
/*
			GLYPHMETRICS gmt;

DWORD GetGlyphOutline(
  HDC hdc,             // handle to DC
  UINT uChar,          // character to query
  UINT uFormat,        // data format
  LPGLYPHMETRICS lpgm, // glyph metrics
  DWORD cbBuffer,      // size of data buffer
  LPVOID lpvBuffer,    // data buffer
  CONST MAT2 *lpmat2   // transformation matrix
);

*/
		/*
		for (int i=0; i < 255; i++)
		{
			ret = GetGlyphOutline( glutarConfig.hDC,
								i,
								GGO_METRICS,
								&gmb[i],
								0, NULL, NULL );
			if (ret == GDI_ERROR)
			{
				isvalid = false;
				//printf("Could not get glyph metrics for (%d) bitmap font \"%s\"\n",i,fname);
			}
		}

		ret = wglUseFontBitmaps( glutarConfig.hDC, 0, 255, baseDList );

		if (ret == FALSE)
		{
			isvalid = false;
			printf("GLFont: Could not create wgl bitmap font for font \"%s\"\n",fname);
		}
		else
			isvalid = true;
			*/
		printf(">>> Bitmap fonts don't work! <<<\n");
		isvalid = false;
	}
	else
	{
		if (lineOnly)	format = WGL_FONT_LINES;
		else				format = WGL_FONT_POLYGONS;

		ret = wglUseFontOutlines( glutarConfig.hDC,	// Select The Current DC
							0,										// Starting Character
							255,									// Number Of Display Lists To Build
							baseDList,							// Starting Display Lists
							0.0f,									// Deviation From The True Outlines
							depth,								// Font Thickness In The Z Direction
							format,								// Use Either Polygons Or Lines
							gmf);									// Address Of Buffer To Recieve Data

		if (ret == FALSE)
		{
			isvalid = false;
			printf("GLFont: Could not create wgl outline font for font \"%s\"\n",fname);
		}
		else
			isvalid = true;

		lineHeight = 0;
		for (int i=0; i < 256; i++)
			lineHeight = max(lineHeight,gmf[i].gmfBlackBoxY);
	}

	SelectObject(glutarConfig.hDC, oldsel);		// Be a good citizen and unselect the font
	DeleteObject(font);									// Still a good citizen -- clear up resources

	if (filename)
		//RemoveFontResourceEx(filename,FR_PRIVATE,0);
		RemoveFontResource(filename);

	xscale = yscale = zscale = 1;

	return;
}

GLFont::~GLFont()											// Destructor -- clean up
{
  glDeleteLists(baseDList, 256);						// Delete All 256 Characters
}

void GLFont::printLeft(const char *fmt, ...)		// Custom GL "Print" Routine - LEFT Justified
{
	float		length=0;											// Used To Find The Length Of The Text
	char		text[256];											// Holds Our String
	va_list		ap;												// Pointer To List Of Arguments

	if (fmt == NULL)												// If There's No Text
		return;														// Do Nothing

	va_start(ap, fmt);											// Parses The String For Variables
	    vsprintf(text, fmt, ap);								// And Converts Symbols To Actual Numbers
	va_end(ap);														// Results Are Stored In Text

	glPushAttrib(GL_LIST_BIT);									// Pushes The Display List Bits
	glListBase(baseDList);										// Sets The Base Character to 0
	glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);	// Draws The Display List Text
	glPopAttrib();													// Pops The Display List Bits
}

void GLFont::printRight(const char *fmt, ...)	// Custom GL "Print" Routine - RIGHT Justified
{
	float		length=0;											// Used To Find The Length Of The Text
	char		text[256];											// Holds Our String
	va_list		ap;												// Pointer To List Of Arguments

	if (fmt == NULL)												// If There's No Text
		return;														// Do Nothing

	va_start(ap, fmt);											// Parses The String For Variables
	    vsprintf(text, fmt, ap);								// And Converts Symbols To Actual Numbers
	va_end(ap);														// Results Are Stored In Text

	for (unsigned int loop=0;loop<(strlen(text));loop++)	// Loop To Find Text Length
		length+=gmf[text[loop]].gmfCellIncX;				// Increase Length By Each Characters Width

	glTranslatef(-length,0.0f,0.0f);							// Right justifty the text on the screen

	glPushAttrib(GL_LIST_BIT);									// Pushes The Display List Bits
	glListBase(baseDList);										// Sets The Base Character to 0
	glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);	// Draws The Display List Text
	glPopAttrib();													// Pops The Display List Bits
}

void GLFont::printCenter(const char *fmt, ...)	// Custom GL "Print" Routine - CENTER Justified
{
	float		length=0;											// Used To Find The Length Of The Text
	char		text[256];											// Holds Our String
	va_list		ap;												// Pointer To List Of Arguments

	if (fmt == NULL)												// If There's No Text
		return;														// Do Nothing

	va_start(ap, fmt);											// Parses The String For Variables
	    vsprintf(text, fmt, ap);								// And Converts Symbols To Actual Numbers
	va_end(ap);														// Results Are Stored In Text

	for (unsigned int loop=0;loop<(strlen(text));loop++)	// Loop To Find Text Length
		length+=gmf[text[loop]].gmfCellIncX;				// Increase Length By Each Characters Width

	//glScalef(xscale,yscale,zscale);
	glTranslatef(-length/2,0.0f,0.0f);						// Center Our Text On The Screen

	glPushAttrib(GL_LIST_BIT);									// Pushes The Display List Bits
	glListBase(baseDList);										// Sets The Base Character to 0
	glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);	// Draws The Display List Text
	glPopAttrib();													// Pops The Display List Bits
}

void GLFont::setScale(GLfloat xs, GLfloat ys, GLfloat zs)
{
	if (!isbitmap)
	{
		xscale = xs;
		yscale = ys;
		zscale = zs;
	}
	else
	{
		xscale = xs/5.0;
		yscale = ys/5.0;
		zscale = zs/5.0;
	}
}

void GLFont::printxyz(GLfloat x, GLfloat y, GLfloat z, const char *fmt, ...)
{
	float		length=0;											// Used To Find The Length Of The Text
	char		text[256];											// Holds Our String
	va_list		ap;												// Pointer To List Of Arguments

	if (fmt == NULL)												// If There's No Text
		return;														// Do Nothing

	va_start(ap, fmt);											// Parses The String For Variables
	    vsprintf(text, fmt, ap);								// And Converts Symbols To Actual Numbers
	va_end(ap);														// Results Are Stored In Text

	glPushMatrix();
	glTranslatef(x,y,z);
	glScalef(xscale,yscale,zscale);

	if (isbitmap)
		glRasterPos3f( x , y , z );

	glPushAttrib(GL_LIST_BIT);									// Pushes The Display List Bits
	glListBase(baseDList);										// Sets The Base Character to 0
	glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);	// Draws The Display List Text
	glPopAttrib();													// Pops The Display List Bits

	glPopMatrix();
}

void GLFont::printxyzRight(GLfloat x, GLfloat y, GLfloat z, const char *fmt, ...)
{
	float		length=0;											// Used To Find The Length Of The Text
	char		text[256];											// Holds Our String
	va_list		ap;												// Pointer To List Of Arguments

	if (fmt == NULL)												// If There's No Text
		return;														// Do Nothing

	va_start(ap, fmt);											// Parses The String For Variables
	    vsprintf(text, fmt, ap);								// And Converts Symbols To Actual Numbers
	va_end(ap);														// Results Are Stored In Text

	glPushMatrix();
	if (!isbitmap)
	{
		glTranslatef(x,y,z);
		glScalef(xscale,yscale,zscale);
	}

	for (unsigned int loop=0;loop<(strlen(text));loop++)	// Loop To Find Text Length
		length+=gmf[text[loop]].gmfCellIncX;				// Increase Length By Each Characters Width

	if (isbitmap)
		glRasterPos3f( x-length , y , z );
	else
		glTranslatef(-length,0.0f,0.0f);							// Right justifty the text on the screen

	glPushAttrib(GL_LIST_BIT);									// Pushes The Display List Bits
	glListBase(baseDList);										// Sets The Base Character to 0
	glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);	// Draws The Display List Text
	glPopAttrib();													// Pops The Display List Bits

	glPopMatrix();
}


void GLFont::printxyzCenter(GLfloat x, GLfloat y, GLfloat z, const char *fmt, ...)
{
	float		length=0;											// Used To Find The Length Of The Text
	char		text[256];											// Holds Our String
	va_list		ap;												// Pointer To List Of Arguments

	if (fmt == NULL)												// If There's No Text
		return;														// Do Nothing

	va_start(ap, fmt);											// Parses The String For Variables
	    vsprintf(text, fmt, ap);								// And Converts Symbols To Actual Numbers
	va_end(ap);														// Results Are Stored In Text

	glPushMatrix();
	if (!isbitmap)
	{
		glTranslatef(x,y,z);
		glScalef(xscale,yscale,zscale);
	}


	if (isbitmap)
	{
		for (unsigned int loop=0;loop<(strlen(text));loop++)	// Loop To Find Text Length
			length+=gmb[text[loop]].gmCellIncX;				// Increase Length By Each Characters Width

		glRasterPos3f( x-length/2.0 , y , z );
		//glRasterPos3f( x , y , z );
		printf("length is: %.3f\n",length);
	}
	else
	{
		for (unsigned int loop=0;loop<(strlen(text));loop++)	// Loop To Find Text Length
			length+=gmf[text[loop]].gmfCellIncX;				// Increase Length By Each Characters Width

		glTranslatef(-length/2.0,0.0f,0.0f);							// Right justifty the text on the screen
	}

	glPushAttrib(GL_LIST_BIT);									// Pushes The Display List Bits
	glListBase(baseDList);										// Sets The Base Character to 0
	glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);	// Draws The Display List Text
	glPopAttrib();													// Pops The Display List Bits

	glPopMatrix();
}


float GLFont::getHeight()
{
	return lineHeight * yscale;
}

float GLFont::getStrWidth(char *text)
{
	float length=0;
	for (unsigned int loop=0;loop<(strlen(text));loop++)	// Loop To Find Text Length
		length+=gmf[text[loop]].gmfCellIncX;				// Increase Length By Each Characters Width

	return length * xscale;
}
