#include "AdeptHeaders.hpp"

#include "GUITextManager.hpp"
#include "GUITextObject.hpp"

//#############################################################################
//###########################    GUIDebugText   ###############################
//#############################################################################

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUIDebugText::GUIDebugText(
	const char *debug_label,
	void *data,
	int type
) :
	Plug(Plug::DefaultData)
{	
	debugLabel = debug_label;
	debugData = data;
	debugType = type;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUIDebugText::~GUIDebugText()
{
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIDebugText::Draw()
{
	Check_Object(this);

	switch(debugType)
	{
	case IntType:
		{
			int *data = (int *)debugData;
			gos_TextDraw("%s :    %d", (char *)debugLabel, *data);
			break;
		}
	case ScalarType:
		{
			Scalar *data = (Scalar *)debugData;
			gos_TextDraw("%s :    %f", (char *)debugLabel, *data);
			break;
		}
	case StringType:
		{
			char *data = (char *)debugData;
			gos_TextDraw("%s :    %s", (char *)debugLabel, data);
			break;
		}
	case Vector3DType:
		{
			Vector3D *data = (Vector3D *)debugData;
			gos_TextDraw("%s :    %3f %3f %3f", (char *)debugLabel, data->x, data->y, data->z);
			break;
		}
	case YawPitchRollType:
		{
			YawPitchRoll *data = (YawPitchRoll *)debugData;
			gos_TextDraw("%s :    %3f %3f %3f", 
				(char *)debugLabel, 
				data->yaw * Degrees_Per_Radian, 
				data->pitch * Degrees_Per_Radian, 
				data->roll * Degrees_Per_Radian
			);
			break;
		}
	};
}
//#######################################################################
//###########################    GUITextManager   #######################
//#######################################################################


GUITextManager::ClassData*
	GUITextManager::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUITextManager::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			GUITextManagerClassID,
			"Adept::GUITextManager",
			Plug::DefaultData
		);
	Check_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUITextManager::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUITextManager::GUITextManager(ClassData *class_data) :
	Plug(class_data),
	guiTextObjects(NULL),
	guiDebugTextObjects(NULL, false)
{
	SPEW(("daberger", "Debug Font should be read in some how and should not be hardcoded!"));
	debugFontHandle = NULL;

#ifdef LAB_ONLY
	debugFontHandle = gos_LoadFont("Assets\\Graphics\\arial8.tga", 0);
#endif

	debugScreenVisible = false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUITextManager::~GUITextManager()
{
	if(!guiDebugTextObjects.IsEmpty())
	{
		guiDebugTextObjects.DeletePlugs();
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUITextManager::ReadObjectsFromNotation(Stuff::NotationFile *gui_contents)
{
	Check_Object(this);
	Check_Pointer(gui_contents);

	NotationFile::PageIterator *pages = gui_contents->MakePageIterator();
	Check_Object(pages);
	Page *page;
	while ((page = pages->ReadAndNext()) != NULL)
	{
		Check_Object(page);
		GUITextObject *gui_object;
		gui_object = new GUITextObject(GUITextObject::DefaultData, page);
		Check_Object(gui_object);
		guiTextObjects.Add(gui_object);
	}
	Check_Object(pages);
	delete pages;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUITextManager::SaveObjectsToStream(Stuff::MemoryStream *stream)
{

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUITextManager::ReadObjectsFromStream(Stuff::MemoryStream *stream)
{

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUITextObject
	*GUITextManager::MakeNewTextObject(
		const char *display_string,
		int x_location,
		int y_location,
		HGOSFONT3D font_handle
	)
{
	Check_Object(this);

	HGOSFONT3D new_font;
	if(!font_handle)
	{
		new_font = gos_LoadFont("Assets\\Graphics\\arial8.tga", 0);
	}
	else
	{
		new_font = font_handle;
	}
	return new GUITextObject(
		GUITextObject::DefaultData,
		new_font,
		display_string,
		x_location,
		y_location
	);
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUITextManager::AddTextObject(GUITextObject *text_object)
{
	Check_Object(this);
	Check_Object(text_object);

	guiTextObjects.Add(text_object);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUITextManager::RemoveTextObject(GUITextObject *text_object)
{
	Check_Object(this);
	Check_Object(text_object);
	
	guiTextObjects.Remove(text_object);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUITextManager::Execute()
{
	Check_Object(this);

	ChainIteratorOf<GUITextObject *> iterator(&guiTextObjects);
	GUITextObject *gui_text_object;

	while((gui_text_object = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(gui_text_object);
		gui_text_object->DrawText();
	}

	//Now last we do the Debug Stuff....if it is visible
#ifdef LAB_ONLY
	if(debugScreenVisible)
	{
		DrawDebugWindow();
	}
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUIDebugText
	*GUITextManager::MakeNewDebugTextObject(
		const char *debug_label,
		void *value,
		int type
	)
{
	Check_Object(this);

	GUIDebugText *gui_text;
	gui_text = 
		new GUIDebugText(
			debug_label,
			value,
			type
		);
	Check_Object(gui_text);
	guiDebugTextObjects.AddValue(gui_text, debug_label);

	return gui_text;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUITextManager::RemoveDebugTextObject(const char *debug_label)
{
	Check_Object(this);

	GUIDebugText *gui_text;

	gui_text = guiDebugTextObjects.Find(debug_label);
	guiDebugTextObjects.Remove(gui_text);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUITextManager::DrawDebugWindow()
{
	Check_Object(this);

	int chain_size;
	SortedChainIteratorOf<GUIDebugText *, MString> iterator(&guiDebugTextObjects);
	chain_size = iterator.GetSize();

	if(chain_size == 0)
	{
		return;
	}
	
	gos_SetRenderState( gos_State_Texture, 0 );
	gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_OneZero );
	gos_SetRenderState( gos_State_Clipping, 0 );
	gos_SetRenderState( gos_State_ZWrite, 0 );
	gos_SetRenderState( gos_State_Filter, gos_FilterNone );
	gos_SetRenderState( gos_State_ZCompare, 0 );
	gos_SetRenderState( gos_State_WireframeMode, 0 );
	gos_SetRenderState( gos_State_Specular, 0 );
	gos_SetRenderState( gos_State_Dither, 0 );
	gos_SetRenderState( gos_State_ShadeMode, gos_ShadeFlat );
	gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulate );
	gos_SetRenderState( gos_State_AlphaTest, 0 );
	gos_SetRenderState( gos_State_Fog, 0 );
	//First we need to Draw the Quad for the Window
	gos_VERTEX quad_verticies[4];
	int y_size = (int)chain_size * 15;
	Max_Clamp(y_size, 470);
	Scalar y_position = (float)y_size + 20;

	quad_verticies[0].rhw	= 1.0;
	quad_verticies[1].rhw	= 1.0;
	quad_verticies[2].rhw	= 1.0;
	quad_verticies[3].rhw	= 1.0;

	quad_verticies[0].x		= 10.0f;
	quad_verticies[0].y		= 10.0f;
	quad_verticies[0].z		= 0.9f;
	quad_verticies[0].argb	= 0xff000055;

	quad_verticies[1].x		= 300.0f;
	quad_verticies[1].y		= 10.0f;
	quad_verticies[1].z		= 0.9f;
	quad_verticies[1].argb	= 0xff000055;

	quad_verticies[2].x		= 300.0f;
	quad_verticies[2].y		= y_position;
	quad_verticies[2].z		= 0.9f;
	quad_verticies[2].argb	= 0xff000055;

	quad_verticies[3].x		= 10.0f;
	quad_verticies[3].y		= y_position;
	quad_verticies[3].z		= 0.9f;
	quad_verticies[3].argb	= 0xff000055;

	gos_DrawQuads(quad_verticies, 4);

	//Second we need to set up all of the String Attributes
	gos_TextSetRegion(10, 10, 300, (int)y_position);
	gos_TextSetAttributes(
		debugFontHandle, 
		0xffffffff, 
		1.0f, 
		false, 
		true, 
		false, 
		false
	);

	//Now we need to draw all of the Debug Streams!
	GUIDebugText *gui_debug_text;
	int count = 1;
	while(((gui_debug_text = iterator.ReadAndNext()) != NULL) && 
		(count <= 23))
	{
		Check_Object(gui_debug_text);
		int y_location = (count * 15) + 5;
		gos_TextSetPosition(20, y_location);
		gui_debug_text->Draw();
		count ++;
	}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUITextManager::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}