#pragma once

#include "volumeshop.h"
#include "Box.h"
#include <string>

class Font
{
public:

	Font() : m_hFont(NULL), m_uBase(0)
	{
		HDC hDC = wglGetCurrentDC();

		if (hDC)
		{
			m_hFont = CreateFont(
				-12,												// Height Of Font
				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
				DEFAULT_QUALITY,						// Output Quality
				FF_SWISS | DEFAULT_PITCH,		// Family And Pitch
				NULL);											// Font Name

			if (m_hFont)
			{
				m_uBase = glGenLists(96);
				HFONT hOldFont = (HFONT) SelectObject(hDC, m_hFont);
				wglUseFontBitmaps(hDC, 32, 96, m_uBase);
				SelectObject(hDC, hOldFont);
			}
		}
	};

	Font (const std::string & strName, const unsigned int uSize = 12, const bool bBold = false, const bool bItalic = false, const bool bUnderline = false, const bool bStrikeout = false)
	{
		HDC hDC = wglGetCurrentDC();

		if (hDC)
		{
			m_hFont = CreateFont(
				-int(uSize),								// Height Of Font
				0,													// Width Of Font
				0,													// Angle Of Escapement
				0,													// Orientation Angle
				bBold ? FW_BOLD : FW_NORMAL,// Font Weight
				bItalic,										// Italic
				bUnderline,									// Underline
				bStrikeout,									// Strikeout
				ANSI_CHARSET,								// Character Set Identifier
				OUT_TT_PRECIS,							// Output Precision
				CLIP_DEFAULT_PRECIS,				// Clipping Precision
				DEFAULT_QUALITY,						// Output Quality
				FF_DONTCARE | DEFAULT_PITCH,// Family And Pitch
				NULL);											// Font Name

			if (m_hFont)
			{
				m_uBase = glGenLists(96);
				HFONT hOldFont = (HFONT) SelectObject(hDC, m_hFont);
				wglUseFontBitmaps(hDC, 32, 96, m_uBase);
				SelectObject(hDC, hOldFont);
			}
		}
	};

	~Font()
	{
		if (m_hFont)
		{
			DeleteObject(m_hFont);									// Delete The Font	
			glDeleteLists(m_uBase, 96);							// Delete All 96 Characters
		}
	};

	void display(const std::string & strText) const
	{
		glPushAttrib(GL_LIST_BIT);
		glListBase(m_uBase - 32);
		glCallLists(strText.size(), GL_UNSIGNED_BYTE, strText.c_str());
		glPopAttrib();
	};

	void display(const Box & boxBox, const std::string & strText) const
	{
		const Box boxBounds = GetBoundingBox(strText);	
		const Vector vecBoxExtent = boxBox.GetExtent();
		const Vector vecBoundsExtent = boxBounds.GetExtent();

		const Vector vecCenter = (vecBoxExtent - vecBoundsExtent) * 0.5f;
		const Vector vecPosition = boxBox.GetMinimum() - boxBounds.GetMinimum();

		glPushAttrib(GL_LIST_BIT | GL_CURRENT_BIT);
		glRasterPos3fv((vecCenter + vecPosition).Get());
		glListBase(m_uBase - 32);
		glCallLists(strText.size(), GL_UNSIGNED_BYTE, strText.c_str());
		glPopAttrib();
	};

	void display(const char *pFormat, ...) const
	{
		if (pFormat == NULL)
			return;

		char vcText[1024];
		va_list ap;

		va_start(ap, pFormat);
		vsprintf(vcText, pFormat, ap);
		va_end(ap);

		display(std::string(vcText));
	};

	void display(const Box & boxBox, const char *pFormat, ...) const
	{
		if (pFormat == NULL)
			return;

		char vcText[1024];
		va_list ap;

		va_start(ap, pFormat);
		vsprintf(vcText, pFormat, ap);
		va_end(ap);

		display(boxBox,std::string(vcText));
	};

	const Box GetBoundingBox(const std::string & strText) const
	{
		SIZE siSize;
		TEXTMETRIC tmMetrics;

		HDC hDC = wglGetCurrentDC();
		HFONT hOldFont = (HFONT) SelectObject(hDC, m_hFont);	
		GetTextExtentPoint32(hDC,strText.c_str(),strText.size(),&siSize);
		GetTextMetrics(hDC,&tmMetrics);
		SelectObject(hDC, hOldFont);

		return Box(Vector(0.0f,float(-tmMetrics.tmDescent),0.0f),Vector(float(siSize.cx),float(-tmMetrics.tmDescent+siSize.cy),0.0f));
	};

private:
	HFONT m_hFont;
	unsigned int m_uBase;
};
