#include "MW4Headers.hpp"
#if !defined(NO_MR)
#include "review_playback.hpp"
#include "missionreview.hpp"
#include "mwapplication.hpp"
#include "ShellScriptHeaders.hpp"
#include "..\missionlang\resource.h"
	
using namespace MechWarrior4;

namespace NMissionReview
{

	Stuff::Scalar m_MapDispX;					// display location of map
	Stuff::Scalar m_MapDispY;
	Stuff::Scalar m_MapDispWidth;
	Stuff::Scalar m_MapDispHeight;

	Stuff::Scalar m_MapTop;						// map coord at topleft of screen
	Stuff::Scalar m_MapLeft;
	Stuff::Scalar m_MapWidth;
	Stuff::Scalar m_MapHeight;
	Stuff::Scalar m_MapScaleX;				// screen coords to map coords
	Stuff::Scalar m_MapScaleY;
	Stuff::Scalar m_MapMeterDisplayX;	// meters to display on the screen
	Stuff::Scalar m_MapMeterDisplayY;

	Stuff::Scalar m_MapTargetLeft,m_MapTargetTop;

	int m_CenteredMech,m_LastCenteredMech;

	bool m_Paused,m_CenteringX,m_CenteringY;

	Stuff::Scalar m_CurrentTime = 0;
	Stuff::Scalar m_LoadedTime = 0;
	Stuff::Scalar m_TotalTime = 0;
	Stuff::Scalar m_SampleRate = 0;
	Stuff::Scalar m_PlayBackRate = 0;
	Stuff::Time m_LastTime=0;
	char m_ReviewMapTexture[128];
	CReviewMap *m_ReviewMap = NULL;
	CReviewTimeBar *m_ReviewTimeBar = NULL;
	CReviewMech *m_ReviewMechs[16] = {
		NULL,NULL,NULL,NULL,
		NULL,NULL,NULL,NULL,
		NULL,NULL,NULL,NULL,
		NULL,NULL,NULL,NULL
	};

	CReviewMap::CReviewMap()
	{
		char tempname[256];
		if (m_ReviewMapTexture[0] == 0)
			sprintf (tempname,"content\\textures\\review\\reviewmap.tga");
		else
			sprintf (tempname,"content\\textures\\%s.tga",m_ReviewMapTexture);
		AddReviewTexture (tempname,0,0,0,256,256,256,256,false);
		Location (Point3D (33,10,0.9f));
		Size (Point3D (400.0f,400.0f,0.9f));
	}

	CReviewMap::~CReviewMap()
	{
	}

	void CReviewMap::DrawImplementation(void)
	{
		Point3D loc,size;
		DWORD color;

		loc.x = m_MapDispX;
		loc.y = m_MapDispY;
		loc.z = 0.9f;
		size.x = m_MapDispWidth;
		size.y = m_MapDispHeight;
		size.z = 0.9f;

		color = MakeColor (0,0,0,255);
//		my_DrawRect (0,0,800,600,color);

		Scalar x1,y1,x2,y2;

		x1 = m_MapLeft;
		y1 = m_MapTop;
		x2 = (m_MapLeft + m_MapMeterDisplayX);
		y2 = (m_MapTop + m_MapMeterDisplayY);

		x1 = x1 * (256.0f / m_MapWidth);
		y1 = y1 * (256.0f / m_MapHeight);
		x2 = x2 * (256.0f / m_MapWidth);
		y2 = y2 * (256.0f / m_MapHeight);

		m_ReviewTextures[0]->TopLeft (x1,y1);
		m_ReviewTextures[0]->BottomRight (x2,y2);
		color = MakeColor (128,255,255,255);
		m_ReviewTextures[0]->BlendMode (gos_BlendDecal);
		m_ReviewTextures[0]->Draw (loc,size,color,ReviewTexture::NO_FLIP);
	}

	CReviewMech::CReviewMech(int id)
	{
		Scalar x,y;
		int i;
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",20,221,0,255,20);			//all
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",0,27,203,59,232);			//leftleg
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",1,27,174,59,203);		//rightleg
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",2,27,87,59,116);		//leftarm
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",3,27,116,59,145);				//rightarm
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",4,27,58,59,87);				//righttorso
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",5,27,29,59,58);		//lefttorso
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",6,27,145,59,174);				//centertorso
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",7,0,0,0,0);			//blank rear?
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",8,27,0,59,29);			//head
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",9,0,0,0,0);			//special1
		AddReviewTexture ("content\\textures\\HUD\\hud256.tga",10,0,0,0,0);		//special2
		Point3D size = m_ReviewTextures[20]->Size ();
		m_ReviewTextures[20]->Origin (size.x/2.0f,size.y/2.0f);
		m_ReviewTextures[20]->Clip (true);
		m_MechID = id;
		x = y = 0;
		switch (m_MechID & 0x03)
		{
		case 0:
			x = 438;
			y = (Scalar) ((m_MechID/4) * 102) + 18;
			break;
		case 1:
			x = 438+84;
			y = (Scalar) ((m_MechID/4) * 102) + 18;
			break;
		case 2:
			x = 438+84+84;
			y = (Scalar) ((m_MechID/4) * 102) + 18;
			break;
		case 3:
			x = 438+84+84+84;
			y = (Scalar) ((m_MechID/4) * 102) + 18;
			break;
		}
		Location (Point3D (x,y,0.9f));
		Size (Point3D (79.0f,90.0f,0.9f));
		m_Name = new HUDText ();
		m_ScoreText1 = new HUDText ();
		m_ScoreText2 = new HUDText ();

		curx = 0;
		cury = 0;
		rot = 0;
		m_Fired = false;
		m_Hit = false;
		m_DamageColors[0] = MakeColor(100, 225, 100, 225);
		m_DamageColors[1] = MakeColor(225, 225, 0, 200);
		m_DamageColors[2] = MakeColor(255, 150, 0, 175);
		m_DamageColors[3] = MakeColor(255, 50, 0, 150);
		m_DamageColors[4] = MakeColor(255, 50, 0, 125);
		m_DamageColors[5] = MakeColor(0, 0, 0, 100);
		for (i=0;i<11;i++)
		{
			m_DamageValues[i] = 0;
		}
	}
	CReviewMech::~CReviewMech()
	{
		delete m_Name;
		delete m_ScoreText1;
		delete m_ScoreText2;
	}
	void CReviewMech::SetMechScore (int s1,int s2,int s3)
	{
		char text[50];
		m_Score1 = s1;
		m_Score2 = s2;
		m_Score3 = s3;
		sprintf (text,"%s:%d",MWApplication::GetInstance ()->GetLocString (IDS_SCOREHUD),s1);
		m_ScoreText1->UpdateText (text);
		sprintf (text,"%d/%d",s2,s3);
		m_ScoreText2->UpdateText (text);
	}

	void CReviewMech::DrawImplementation(void)
	{
		DWORD color;
		int i;
		bool draw;

		Point3D loc,size;
		loc = Location ();

		size = m_ReviewTextures[0]->Size ();
		for (i=0;i<11;i++)
		{
			if (i==7)
				continue;
			if (i==9)
				continue;
			if (i==10)
				continue;
			Verify (m_ReviewTextures[i]);
			if ((m_DamageValues[i] <= 5) && (m_DamageValues[i]>=0))
			{
//				if ((m_DamageValues[i] != 4) || (m_DamageFlash))
				{
					m_ReviewTextures[i]->Draw (Point3D (loc.x+25,loc.y+21,loc.z),size,m_DamageColors[m_DamageValues[i]]);
				}
			}
		}

		size = m_ReviewTextures[20]->Size ();
		if (m_Fired)
			color = MakeColor (255,255,0,250);
		else if (m_Hit)
			color = MakeColor (255,0,0,250);
		else
			color = MakeColor (0,255,0,250);

		loc.x = (curx) * m_MapWidth ;				// convert to map coords
		loc.y = (cury) * m_MapHeight ;
		draw = true;
		if (loc.x < m_MapLeft)
			draw = false;
		if (loc.y < m_MapTop)
			draw = false;
		if (loc.x > (m_MapLeft+m_MapMeterDisplayX))
			draw = false;
		if (loc.y > (m_MapTop+m_MapMeterDisplayY))
			draw = false;
		loc.x -= m_MapLeft;
		loc.y -= m_MapTop;
		loc.x *= m_MapScaleX;														// convert to screen coords
		loc.y *= m_MapScaleY;
		loc.x += m_MapDispX;														// offset for map location on screen.
		loc.y += m_MapDispY;
		if ((loc.x < 0) || (loc.y < 0))
			draw = false;
		if ((loc.x > (m_MapDispX+m_MapDispWidth)) || (loc.y > (m_MapDispY+m_MapDispHeight)))
			draw = false;
		Scalar iconheight = size.y;
		Scalar tx=0,ty=0;
		if (draw)
		{
			m_ReviewTextures[20]->Rotate (Pi - rot);
			m_ReviewTextures[20]->Scale (0.5f,0.5f);
			m_ReviewTextures[20]->Draw (loc,size,color);
			tx = loc.x;
			ty = loc.y;
		}

		loc = Location ();
		size = Size ();
		color = MakeColor (128,128,128,250);
		DWORD dx,dy;
		Point3D textloc;
		textloc.x = loc.x + (size.x/2.0f);
		textloc.y = loc.y;
		textloc.z = 0.9f;
		m_Name->TopLeft (textloc.x-50.0f,textloc.y-1.9f);
		m_Name->BottomRight (textloc.x+50.0f,textloc.y+20.0f);
		m_Name->Color (color);
		m_Name->Justification (HUDText::LEFT_ALIGN);
		m_Name->DrawSize (dx,dy);
		textloc.x -= dx/2;
		m_Name->Draw (textloc);
		if (draw)
		{
			m_Name->Color (255,255,255,255);
			textloc.x = tx-(dx/2);
			textloc.y = ty + (iconheight/2) + 2;
			m_Name->Draw (textloc);
		}

		
		textloc.x = loc.x + (size.x/2.0f);
		textloc.y = loc.y + 60;
		textloc.z = 0.9f;
		m_ScoreText1->TopLeft (textloc.x-50.0f,textloc.y-2.0f);
		m_ScoreText1->BottomRight (textloc.x+50.0f,textloc.y+20.0f);
		m_ScoreText1->Color (color);
		m_ScoreText1->Justification (HUDText::LEFT_ALIGN);
		m_ScoreText1->DrawSize (dx,dy);
		textloc.x -= dx/2;
		m_ScoreText1->Draw (textloc);
		
		textloc.x = loc.x + (size.x/2.0f);
		textloc.y = loc.y + 75;
		textloc.z = 0.9f;
		m_ScoreText2->TopLeft (textloc.x-50.0f,textloc.y-2.0f);
		m_ScoreText2->BottomRight (textloc.x+50.0f,textloc.y+20.0f);
		m_ScoreText2->Color (color);
		m_ScoreText2->Justification (HUDText::LEFT_ALIGN);
		m_ScoreText2->DrawSize (dx,dy);
		textloc.x -= dx/2;
		m_ScoreText2->Draw (textloc);
	}

	CReviewTimeBar::CReviewTimeBar()
	{
		Location (Point3D (55.0f,422.0f,0.9f));
		Size (Point3D (690.0f,20.0f,0.9f));
	}
	CReviewTimeBar::~CReviewTimeBar()
	{
	}
	void CReviewTimeBar::DrawImplementation(void)
	{
		DWORD color;

		Point3D loc,size;
		loc = Location ();
		size = Size ();
		color = MakeColor (128,128,128,250);
		my_DrawRect ((int) loc.x,(int) loc.y,(int) (loc.x+size.x),(int) (loc.y+size.y),color);
		color = MakeColor (0,0,0,250);
		DrawFrame ((int) loc.x,(int) loc.y,(int) (loc.x+size.x),(int) (loc.y+size.y),color);

		if (m_TotalTime == 0)
			loc.x = 0;
		else
			loc.x = (size.x-size.y) / m_TotalTime;
		loc.x *= m_CurrentTime;
		loc.x += 55.0f;
		size.x = size.y;			
		if ((loc.x+size.x) > 745.0f)
			loc.x = 745.0f - size.x;

		color = MakeColor (0,250,0,250);
		my_DrawRect ((int) loc.x,(int) loc.y,(int) (loc.x+size.x),(int) (loc.y+size.y),color);
		color = MakeColor (0,0,0,250);
		DrawFrame ((int) loc.x,(int) loc.y,(int) (loc.x+size.x),(int) (loc.y+size.y),color);
		
		size = Size ();
		if (m_TotalTime == 0)
			loc.x = 0;
		else
			loc.x = (size.x) / m_TotalTime;
		loc.x *= m_LoadedTime;
		loc.x += 5.0f;
		if ((loc.x) > 795.0f)
			loc.x = 795.0f;
		color = MakeColor (0,0,0,250);
		DrawLine ((int) loc.x,(int) loc.y,(int) loc.x,(int) (loc.y+size.y),color);
	}

	void InitMissionReviewDisplay (void)
	{
		int i;
		m_LastCenteredMech = -1;
		m_MapDispX = 23;
		m_MapDispY = 10;
		m_MapDispWidth = 400.0f;
		m_MapDispHeight = 400.0f;
		m_MapTop = 0.0f;
		m_MapLeft = 0.0f;
		m_MapTargetLeft = 0.0f;
		m_MapTargetTop = 0.0f;
		m_MapWidth = 5120.0f;
		m_MapHeight = 5120.0f;
		m_Paused = false;
		m_CenteringX = m_CenteringY = false;
		m_CenteredMech = 0;

		m_MapMeterDisplayX = 1000;
		m_MapMeterDisplayY = 1000;
		m_MapScaleX = m_MapDispWidth / m_MapMeterDisplayX;
		m_MapScaleY = m_MapDispHeight / m_MapMeterDisplayY;

		m_CurrentTime = 0;
		m_LoadedTime = 0;
		m_TotalTime = 0;
		m_SampleRate = 0;
		m_PlayBackRate = 1;
		m_LastTime = gos_GetElapsedTime ();
		MWApplication *app = MWApplication::GetInstance ();
		Check_Object (app);
//		m_ReviewLog = app->m_playLog;
		Verify (app->m_playLog);
		app->m_playLog->GetLogTimes (m_LoadedTime,m_TotalTime,m_SampleRate);
		m_ReviewMap = new CReviewMap ();
		m_ReviewMap->Show ();
		m_ReviewTimeBar = new CReviewTimeBar ();
		m_ReviewTimeBar->Show ();
		for (i=0;i<16;i++)
		{
			m_ReviewMechs[i] = new CReviewMech (i);
			m_ReviewMechs[i]->Show ();
		}
	}

	void KillMissionReviewDisplay (void)
	{
//		m_ReviewLog = NULL;
		delete m_ReviewMap;
		m_ReviewMap = NULL;

		delete m_ReviewTimeBar;
		m_ReviewTimeBar = NULL;
		int i;
		for (i=0;i<16;i++)
		{
			delete m_ReviewMechs[i];
			m_ReviewMechs[i] = NULL;
		}
	}

	void PlayMissionReview (Stuff::Time time)
	{
		int i;
		MWApplication *app = MWApplication::GetInstance ();
		Check_Object (app);
		if (!app->m_playLog)
		{
			return;
		}

		ReadKeyboard ();

		app->m_playLog->GetLogTimes (m_LoadedTime,m_TotalTime,m_SampleRate);
		if (!m_Paused)
		{
			m_CurrentTime += (Scalar) ((gos_GetElapsedTime () - m_LastTime) * m_PlayBackRate);
		}

		Max_Clamp (m_CurrentTime,m_LoadedTime);

		m_LastTime = gos_GetElapsedTime ();

		for (i=0;i<16;i++)
			m_ReviewMechs[i]->Hide ();
		if (m_LoadedTime != 0)
		{
			int currentmech = 0;
			for (i = 0; i < Maximum_Players; ++i)
			{
				{
					MRPlayerData player_data;
					app->m_playLog->GetPlayerData(&player_data, m_CurrentTime, i);
			
					if ((player_data.m_playerStatus == MRPlayerData::InToken) && (player_data.m_alive))
					{
						m_ReviewMechs[currentmech]->Show ();
						m_ReviewMechs[currentmech]->SetMechCoord (1.0f-player_data.m_position.x,1.0f-player_data.m_position.z);
						m_ReviewMechs[currentmech]->SetMechRot (player_data.m_yawRotation);
						m_ReviewMechs[currentmech]->SetMechFired (player_data.m_firedWeapon);
						m_ReviewMechs[currentmech]->SetMechHit (player_data.m_takenDamage);
						m_ReviewMechs[currentmech]->SetMechDamageLevel (player_data.m_damageLevel);
						m_ReviewMechs[currentmech]->SetMechName (player_data.m_playerName);
						m_ReviewMechs[currentmech]->SetMechScore ((int) player_data.m_scoreBucket1,(int) player_data.m_scoreBucket2,(int) player_data.m_scoreBucket3);
						if (currentmech == m_CenteredMech)
						{
							if (currentmech != m_LastCenteredMech)
							{
								m_MapLeft = (1.0f - player_data.m_position.x) * m_MapWidth;
								m_MapTop = (1.0f - player_data.m_position.z) * m_MapHeight;
								m_MapLeft -= (m_MapMeterDisplayX/2.0f);
								m_MapTop -= (m_MapMeterDisplayY/2.0f);
								m_LastCenteredMech = currentmech;
							}
							m_MapTargetLeft = (1.0f - player_data.m_position.x) * m_MapWidth;
							m_MapTargetTop = (1.0f - player_data.m_position.z) * m_MapHeight;
							m_MapTargetLeft -= (m_MapMeterDisplayX/2.0f);
							m_MapTargetTop -= (m_MapMeterDisplayY/2.0f);
							Min_Clamp (m_MapTargetTop,0);
							Min_Clamp (m_MapTargetLeft,0);
							Max_Clamp (m_MapTargetTop,m_MapHeight-m_MapMeterDisplayY);
							Max_Clamp (m_MapTargetLeft,m_MapWidth-m_MapMeterDisplayX);
						}
						currentmech++;
					}
				}
			}
		}

		if (!m_CenteringX)
		{
			if (abs ((int) (m_MapTargetLeft - m_MapLeft)) > 450)
			{
				m_CenteringX = true;
			}
		}
		if (!m_CenteringY)
		{
			if (abs(int (m_MapTargetTop - m_MapTop)) > 450)
			{
				m_CenteringY = true;
			}
		}

		if (m_CenteringX)
		{
			if (abs ((int) (m_MapTargetLeft - m_MapLeft)) < 5)
			{
				m_CenteringX = false;
			}
			else
			{
				Scalar delta = m_MapTargetLeft - m_MapLeft;
				Clamp (delta,-10,10);
				m_MapLeft+= delta;
			}
		}
		if (m_CenteringY)
		{
			if (abs(int (m_MapTargetTop - m_MapTop)) < 5)
			{
				m_CenteringY = false;
			}
			else
			{
				Scalar delta = m_MapTargetTop - m_MapTop;
				Clamp (delta,-10,10);
				m_MapTop+= delta;
			}
		}

		gos_PushRenderStates ();
		HUDTexture::StartTexturePass ();

    gos_SetRenderState (gos_State_Filter,gos_FilterBiLinear);
		m_ReviewMap->Draw (true);
		m_ReviewTimeBar->Draw (true);
		for (i=0;i<16;i++)
			m_ReviewMechs[i]->Draw (true);

		HUDTexture::EndTexturePass ();
		gos_PopRenderStates ();
	}

	int SpeedUp (void)
	{
		m_PlayBackRate++;
		Clamp (m_PlayBackRate,1,10);
		return 0;
	}
	
	int SlowDown (void)
	{
		m_PlayBackRate--;
		Clamp (m_PlayBackRate,1,10);
		return 0;
	}
	
	int Rewind (void)
	{
		m_CurrentTime = 0;
		return 0;
	}
	
	int Pause (void)
	{
		m_Paused = !m_Paused;
		return 0;
	}

	int CenterOn (void *data[], int count)
	{
		int id = *(INTARRAYPARAM(1));

		if (!m_ReviewMechs[id]->Visible ())
			return 0;
		m_CenteredMech = id;
		m_LastCenteredMech = -1;
		return 0;
	}

	void ReadKeyboard (void)
	{
#if 0
		int keypress = gos_GetKey () & 255;
		while (keypress)
		{
			switch (keypress)
			{
			case 'f':
				SpeedUp ();
			break;
			case 's':
				SlowDown ();
			break;
			case 'r':
				Rewind ();
			break;
			case 'p':
				Pause ();
			break;
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				CenterOn (keypress - '0');
			break;
			}
			keypress = gos_GetKey () & 255;
		}
#endif
	}

}


#endif // !defined(NO_MR)
