#include "MW4Headers.hpp" 

#include "GUIStaticView.hpp"

#include <ElementRenderer\StateChange.hpp>
#include <ElementRenderer\ScreenQuadsElement.hpp>
#include <ElementRenderer\CameraElement.hpp>

#include <MLR\MLRTexture.hpp>
#include <MLR\MLRTexturePool.hpp>

using MidLevelRenderer::MLRTexturePool;
using MidLevelRenderer::MLRTexture;


ElementRenderer::CameraElement
	*GUIStaticView::s_Camera = NULL;
bool
	GUIStaticView::s_MarkForAttach = false;

const Stuff::Scalar c_ONE_OVER_256 = (1.0f / 256.0f);
//#######################################################################
//###########################    GUIWeaponManager   #####################
//#######################################################################

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUIStaticView::GUIStaticView() :
	Plug(Plug::DefaultData),
	m_screenTiles(NULL)
{
	m_numTiles = 0;
	isShown = false;
	ChangeResolution();
	Hide();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUIStaticView::~GUIStaticView()
{
	if(m_screenTiles.GetCurrent())
	{
		delete m_screenTiles.GetCurrent();
		m_screenTiles.Remove();
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIStaticView::Initialize()
{
	Check_Object(this);

	s_MarkForAttach = false;
	m_numTiles = 0;
	isShown = false;
	ChangeResolution();
	Hide();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIStaticView::ChangeResolution()
{
	Check_Object(this);

	if(m_screenTiles.GetCurrent())
	{
		delete m_screenTiles.GetCurrent();
		m_screenTiles.Remove();
	}


	Scalar ratio = 256.0f / Environment.screenHeight;
	int left_over = Environment.screenHeight % 256;

	m_numTiles = (int)((Environment.screenHeight * c_ONE_OVER_256) + 1);

	gos_PushCurrentHeap(ElementRenderer::ScreenQuadsElement::s_Heap);
	ElementRenderer::ScreenQuadsElement *screen_tiles = 
		new ElementRenderer::ScreenQuadsElement(m_numTiles);
	gos_PopCurrentHeap();

	for(int i=0; i<m_numTiles; i++)
	{
		//Pointers into the screen quad
		Vector4D *poly_corners;
		RGBAColor *poly_colors;
		Vector2DOf<Scalar> *poly_UVs;
		bool *poly_status;

		Vector4D corners[4];
		RGBAColor colors[4];
		Vector2DOf<Scalar> UVs[4];

		screen_tiles->GetQuadData(
			i, 
			&poly_corners, 
			&poly_colors,
			&poly_UVs,
			&poly_status
		);

		colors[0].red = colors[1].red = colors[2].red = colors[3].red = 1.0f;
		colors[0].green = colors[1].green = colors[2].green = colors[3].green = 1.0f;
		colors[0].blue = colors[1].blue = colors[2].blue = colors[3].blue = 1.0f;
		colors[0].alpha = colors[1].alpha = colors[2].alpha = colors[3].alpha = 1.0f;

		Mem_Copy(poly_colors, colors, 4 * sizeof(RGBAColor), 4 * sizeof(RGBAColor));

		UVs[0].x = 0.0f;
		UVs[0].y = 0.0f;
		UVs[1].x = 0.0615f;
		UVs[1].y = 0.0f;
		UVs[2].x = 0.0615f;
		if((i + 1) <m_numTiles)
			UVs[2].y = 1.0f;
		else
			UVs[2].y = left_over * c_ONE_OVER_256;
		UVs[3].x = 0.0f;
		UVs[3].y = UVs[2].y;

		Mem_Copy(poly_UVs, UVs, 4 * sizeof(Vector2DOf<Scalar>), 4 * sizeof(Vector2DOf<Scalar>));
	
		corners[0].x = 0.0f;
		if(i > 0)
			corners[0].y = i * ratio/* - 1.0f / Environment.screenHeight*/;
		else
			corners[0].y = 0.0f;
		corners[1].x = 1.0f;
		corners[1].y = corners[0].y;

		corners[2].x = 1.0f;
		if((i + 1) <m_numTiles)
			corners[2].y = (i + 1) * ratio/* - 1.0f / Environment.screenHeight*/;
		else
			corners[2].y = 1.0f;
		corners[3].x = 0.0f;
		corners[3].y = corners[2].y;

		corners[0].z = 0.0f;
		corners[0].w = 1.0f;
		corners[1].z = 0.0f;
		corners[1].w = 1.0f;
		corners[2].z = 0.0f;
		corners[2].w = 1.0f;
		corners[3].z = 0.0f;
		corners[3].w = 1.0f;

		Mem_Copy(poly_corners, corners, 4 * sizeof(Vector4D), 4 * sizeof(Vector4D));

		*poly_status = IsOn();
	}

	ElementRenderer::StateChange *state_change = new ElementRenderer::StateChange();
	Check_Object(MLRTexturePool::Instance);
	MLRTexture *quad_texture = (*MLRTexturePool::Instance)("Static", 0);
	if(!quad_texture)
	{
		quad_texture = MLRTexturePool::Instance->Add("Static", 0);
	}
	Check_Object(quad_texture);
	state_change->SetTextureHandle(quad_texture->GetTextureHandle());
//	state_change->SetAlphaMode(ElementRenderer::StateChange::AlphaInvAlphaMode);
	state_change->SetAlphaMode(MidLevelRenderer::MLRState::OneOneMode);
	state_change->SetRenderPriority(ElementRenderer::StateChange::HUDPriority0);

	state_change->DisableBackfaceCulling();
	state_change->DisableChildBackfaceControl();

	state_change->SetFogMode(ElementRenderer::StateChange::DisableFogMode);
	state_change->DisableChildFogControl();

	state_change->DisableZBufferWrite();
	state_change->DisableChildZBufferWriteControl();

	state_change->DisableZBufferCompare();
	state_change->DisableChildZBufferCompareControl();

//	state_change->DisableTextureWrap();
	state_change->EnableTextureWrap();
	state_change->DisableChildTextureWrapControl();

	screen_tiles->AdoptStateChange(state_change);

	m_screenTiles.Add(screen_tiles);
	if(s_Camera)
	{
		s_Camera->AttachChild(m_screenTiles.GetCurrent());
		m_screenTiles.GetCurrent()->Sync();
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIStaticView::Hide()
{
	Check_Object(this);

	for(int i=0; i<m_numTiles; i++)
	{
		m_screenTiles.GetCurrent()->SetQuadStatus(i, false);
	}
	isShown = false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIStaticView::Show()
{
	Check_Object(this);

	for(int i=0; i<m_numTiles; i++)
	{
		m_screenTiles.GetCurrent()->SetQuadStatus(i, true);
	}
	if(s_MarkForAttach)
	{
		s_Camera->AttachChild(m_screenTiles.GetCurrent());
		m_screenTiles.GetCurrent()->Sync();
		s_MarkForAttach = false;
	}

	isShown = true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIStaticView::Animate()
{
	//
	// Pick new, random UV coordinates
	//
	Stuff::Scalar  fUVx = ((float)Stuff::Random::GetLessThan(256))*c_ONE_OVER_256;
	Stuff::Scalar  fUVy = ((float)Stuff::Random::GetLessThan(256))*c_ONE_OVER_256;
	int left_over = Environment.screenHeight % 256;
	for(int i=0; i<m_numTiles; i++)
	{
		//Pointers into the screen quad
		Vector4D *poly_corners;
		RGBAColor *poly_colors;
		Vector2DOf<Scalar> *poly_UVs;
		bool *poly_status;

		Vector4D corners[4];
		RGBAColor colors[4];
		Vector2DOf<Scalar> UVs[4];

		m_screenTiles.GetCurrent()->GetQuadData(
			i, 
			&poly_corners, 
			&poly_colors,
			&poly_UVs,
			&poly_status
		);


/*	UVs[0].x = 0.0f;
		UVs[0].y = 0.0f;
		UVs[1].x = 0.0615f;
		UVs[1].y = 0.0f;
		UVs[2].x = 0.0615f;
		if((i + 1) <m_numTiles)
			UVs[2].y = 1.0f;
		else
			UVs[2].y = left_over / 256.0f;
		UVs[3].x = 0.0f;
		UVs[3].y = UVs[2].y;
*/
  	UVs[0].x = fUVx;
		UVs[0].y = fUVy;;
		UVs[1].x = fUVx + 1.0f;
		UVs[1].y = fUVy;
		UVs[2].x = UVs[1].x;
		if((i + 1) <m_numTiles)
			UVs[2].y = fUVy + 1.0f;
		else
			UVs[2].y = fUVy + (left_over * c_ONE_OVER_256)/* *1.0f*/;
		UVs[3].x = fUVx;
		UVs[3].y = UVs[2].y;

		Mem_Copy(poly_UVs, UVs, 4 * sizeof(Vector2DOf<Scalar>), 4 * sizeof(Vector2DOf<Scalar>));
	
	}


}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIStaticView::AdoptCamera(ElementRenderer::CameraElement *camera)
{
	Check_Pointer(camera);

	s_Camera = camera;
	s_MarkForAttach = true;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIStaticView::RemoveCamera()
{
	s_Camera = NULL;
}