//
// Asura_Text_Output.cpp
//
// Created by Kevin Lea - 12/06/2001 11:06:03
// 
// Copyright (C) 2001 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

#include "Rendering/Asura_Text_Output.h"

// Kevin Lea - 05/10/2001 15:11:28 - hey! I'm being naughty have the stuff below in Independent code
// I guess the primary use of this is debugging text, but eventually we'll need nicer text display stuff

#include <stdarg.h> // for using variable arguments (va_list, etc.)
#include <stdio.h> // for vsprintf
#include "Core/Asura_Maths.h"

#include "ChunkSystem/Asura_Chunk_Loaders.h"
#include "Rendering/Asura_Font_System.h"
#include "Rendering/Asura_Render.h"
#include "COre/Asura_TextureManagement.h"


static const Asura_Char* FontFilename = "\\tools\\font.dds";
Asura_Handle Asura_Text_Output::s_iSmallFontHandle = ASURA_INVALID_HANDLE;

int Asura_Text_Output::FontTextureIndex = ASURA_TEXTURE_NONE;

void Asura_Text_Output::Initialise(void)
{
	// KJL 26/05/00 12:24:44 - load texture
	FontTextureIndex = Asura_Texture_Management::AddTexture(FontFilename);
}

bool Asura_Text_Output::IsInitialised()
{
	return FontTextureIndex != ASURA_TEXTURE_NONE;
}

void Asura_Text_Output::LoadFonts()
{
	if(!Asura_Font_System::IsFontLoaded("\\fonts\\Arial_9"))
	{
		// (MH - 02.07.2004) fonts are not unloaded when Asura_Core::Reset() is called, so we need to 
		// load the texture permanently as well.
		// LoadAsuraFile("Fonts\\Tools\\ToolsFont.asr");
		Asura_Texture_Management::LoadAsuraFileUsingResetGroup("Fonts\\Tools\\ToolsFont.asr", ASURA_TEXTURE_LOADED_PERMANENT );
	}
	s_iSmallFontHandle = Asura_Font_System::GetFontHandle("\\fonts\\Arial_9");
}

void Asura_Text_Output::Print(float x, float y, unsigned int colour, int formatflags, const char* string, ...)
{
	// KJL 26/07/00 12:11:30 - possible problem in this function is expanded string is bigger than the set size...
	// difficult to see how to find length of expanded string before it is parsed, etc.
	
	char buffer[255];
	char* stringPtr = buffer;


	// KJL 26/07/00 12:02:01 - format string and place in buffer
	{
		va_list ap;
		va_start(ap, string);
		Asura_PrintfToBfr(buffer,string,ap,255,true);
		va_end(ap);
	}

	// KJL 26/07/00 12:12:56 - any special formatting required?
	if (formatflags)
	{
		
		float fWidth = WidthOfString(buffer,formatflags);

		if (formatflags&ASURA_TEXT_FORMAT_RIGHTJUSTIFIED)
		{
			x -= fWidth;
		}
		else if (formatflags&ASURA_TEXT_FORMAT_CENTREJUSTIFIED)
		{
			x -= fWidth/2;
		}
	}

	x*=ASURA_TEXT_OUTPUT_FONT_WIDTH;
	y*=ASURA_TEXT_OUTPUT_FONT_HEIGHT;


	if((formatflags & ASURA_TEXT_FORMAT_SMALLFONT) && (s_iSmallFontHandle != ASURA_INVALID_HANDLE))
	{
  	    //use the font system font instead
		u_int uFormat = ASURA_TEXTFORMAT_FORMATSTRING;

		x = (float)Asura_Maths::FloatToInt(x);
		y = (float)Asura_Maths::FloatToInt(y);
  	    Asura_Font_System::SetFont(s_iSmallFontHandle);
		Asura_Font_System::Print(x,y,colour,uFormat,"%s",buffer);
		return;
		
	}
	

	// KJL 26/05/00 12:25:29 - each letter is drawn as a series of quads
	Asura_Render::Overlay.Colour = colour;
	Asura_Render::Overlay.TextureIndex = FontTextureIndex;
	Asura_Render::Overlay.TranslucencyMode = ASURA_TRANSLUCENCY_NORMAL;

	x=Asura_Maths::FloatToInt(x)-0.5f;
	y=Asura_Maths::FloatToInt(y)-0.5f;

	Asura_Render::Overlay.Y[0] = y;
	Asura_Render::Overlay.Y[1] = y;
	Asura_Render::Overlay.Y[2] = y + ASURA_TEXT_OUTPUT_FONT_HEIGHT;
	Asura_Render::Overlay.Y[3] = y + ASURA_TEXT_OUTPUT_FONT_HEIGHT;

    //Make sure text doesn't get done in wireframe. RAR 14/05/03
	Asura_Render::CurrentStates.RequestWireFrameMode( false );


	while( *stringPtr )
	{
		char c = *stringPtr++; 
		
		if (c!=' ')
		{
			float topLeftU = (float)(1+((c)&15)*16)/256.0f;
			float topLeftV = (float)(1+((c)>>4)*16)/256.0f;
			float delta = 0.0f;//1.0f/256.0f;
			float deltaWidth = ASURA_TEXT_OUTPUT_FONT_WIDTH/256.0f+delta;
			float deltaHeight =ASURA_TEXT_OUTPUT_FONT_HEIGHT/256.0f+delta;

			Asura_Render::Overlay.U[0] = topLeftU + delta;
			Asura_Render::Overlay.V[0] = topLeftV + delta;
			Asura_Render::Overlay.U[1] = topLeftU + deltaWidth;
			Asura_Render::Overlay.V[1] = topLeftV + delta;
			Asura_Render::Overlay.U[2] = topLeftU + deltaWidth;
			Asura_Render::Overlay.V[2] = topLeftV + deltaHeight;
			Asura_Render::Overlay.U[3] = topLeftU + delta;
			Asura_Render::Overlay.V[3] = topLeftV + deltaHeight;
			
			Asura_Render::Overlay.X[0] = x ;
			Asura_Render::Overlay.X[3] = x ;
			Asura_Render::Overlay.X[1] = x + ASURA_TEXT_OUTPUT_FONT_WIDTH ;
			Asura_Render::Overlay.X[2] = x + ASURA_TEXT_OUTPUT_FONT_WIDTH ;
				
			Asura_Render::Overlay.m_bNonRotated = true;
			Asura_Render::Overlay.Render();
		}
		x += ASURA_TEXT_OUTPUT_FONT_WIDTH;
	
	
	}
}

int  Asura_Text_Output::LengthOfString(const char *string, ...)
{
	// KJL 26/07/00 12:11:30 - possible problem in this function is expanded string is bigger than the set size...
	// difficult to see how to find length of expanded string before it is parsed, etc.
	
	char buffer[255];
	char *stringPtr = buffer;

	// KJL 26/07/00 12:02:01 - format string and place in buffer
	{
		va_list ap;
		va_start(ap, string);
		Asura_PrintfToBfr(buffer,string,ap,255,true);
		va_end(ap);
	}

	int length=0;
	while(*stringPtr++!=0) length++;
	return (length+1);
}

void Asura_Text_Output::ConvertPixelsToPrintCoords(float& x, float& y)
{
	x /= ASURA_TEXT_OUTPUT_FONT_WIDTH;
	y /= ASURA_TEXT_OUTPUT_FONT_HEIGHT;
}

float Asura_Text_Output::WidthOfString(const char* pszString,int iFormat)
{
	if(!pszString) return 0;

	if((iFormat & ASURA_TEXT_FORMAT_SMALLFONT) && (s_iSmallFontHandle != ASURA_INVALID_HANDLE))
	{
  	    Asura_Font_System::SetFont(s_iSmallFontHandle);
		float fPixelWidth = Asura_Font_System::GetWidthOfString(pszString);
		return fPixelWidth/ASURA_TEXT_OUTPUT_FONT_WIDTH;
	}
	else
	{
		return (float) strlen(pszString);
	}
}

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_Text_Output::HeightOfString
// Author       : Andy Tate
// Date         : 8-May-2007
////////////////////////////////////////////////////////////////////////////////

float Asura_Text_Output::HeightOfString(const char* pszString,
										int iFormat)
{
	if(pszString == NULL)
	{
		return(0.0f);
	}
	else
	{
		float		fHeight				= 1.0f;
		const char*	pcCurrentCharacter	= pszString;

		while(*pcCurrentCharacter != '\0')
		{
			if(*pcCurrentCharacter == '\n')
			{
				fHeight	+= 1.0f;
			}

			pcCurrentCharacter++;
		}

		return(fHeight);
	}
}

/// End of function 'Asura_Text_Output::HeightOfString'. ///


/// End of string. ///
