#include "MW4Headers.hpp"

#include "GUIWeaponManager.hpp"
#include "VehicleInterface.hpp"
#include "MWGUIManager.hpp"
#include "Weapon.hpp"
#include "AI_DebugRenderer.hpp"
#include "ShellScriptHeaders.hpp"

#include <MLR\MLR.hpp>

GUIWeapon::ClassData*
	GUIWeapon::DefaultData = NULL;

using namespace MidLevelRenderer;

DECLARE_TIMER(static, Weapon_Text_Draw);

//#######################################################################
//#########################		GUIWeapon		#########################
//#######################################################################

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIWeapon::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			GUIWeaponClassID,
			"MechWarrior4::GUIWeapon",
			Plug::DefaultData
		);
	Register_Object(DefaultData);
}

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUIWeapon::GUIWeapon(
	const char *weapon_name,
	Scalar weapon_count,
	RGBAColor *weapon_color,
	int *ammo_count,
	Weapon *weapon
) :
	Plug(DefaultData)
{
	int length = strlen(weapon_name);
	Verify(length > 0);
	length ++;
	weaponName = new char [length];
	Register_Pointer(weapon_name);

	Str_Copy(weaponName, weapon_name, length + 1);
	weaponCount = weapon_count;
	weaponColor.alpha = weapon_color->alpha;
	weaponColor.red = weapon_color->red;
	weaponColor.green = weapon_color->green;
	weaponColor.blue = weapon_color->blue;
	readyColor.alpha =  weapon_color->alpha;
	readyColor.red =  weapon_color->red;
	readyColor.green =  weapon_color->green;
	readyColor.blue =  weapon_color->blue;
	
	ammoCount = ammo_count;

	m_weapon = weapon;
	m_status = ReadyStatus;
	const Weapon__GameModel *model = weapon->GetGameModel ();
	m_Range = model->maxDistance;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUIWeapon::~GUIWeapon()
{
	Check_Object(this);

	Unregister_Pointer(weaponName);
	delete [] weaponName;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIWeapon::Draw(int y_location)
{
	Check_Object(this);
	DWORD gos_color = MidLevelRenderer::GOSCopyColor(&weaponColor);
	char text_string[128];
	sprintf(text_string, "/color=%8x%s :", gos_color, weaponName);
	gos_TextDraw(text_string);
	gos_TextSetPosition((int)(0.895f * Environment.screenWidth), y_location);
	sprintf(text_string, "/color=%8x%.3f",gos_color, weaponCount);
	gos_TextDraw(text_string);
	if(DECRYPT(*ammoCount) != -1)
	{
		gos_TextSetPosition((int)(0.95f * Environment.screenWidth), y_location);
		sprintf(text_string, "/color=%8x%d",gos_color, DECRYPT(*ammoCount));
		gos_TextDraw(text_string);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIWeapon::Reload()
{
	Check_Object(this);
	
	SetStatus(ReloadingStatus);
	weaponColor.red = 1.0f;
	weaponColor.green = 0.0f;
	weaponColor.blue = 0.0f;
}

// MSL 5.03 RTX
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void GUIWeapon::RecoverFromFire()
{
	Check_Object(this);

	SetStatus(AmmoFireStatus);

	weaponColor.red = 1.0f;
	weaponColor.green = 0.0f;
	weaponColor.blue = 0.0f;
}

// MSL 5.03 RTX
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void GUIWeapon::RecoverFromJam()
{
	Check_Object(this);

	//check if we are a rotary autocannon?
	SetStatus(JammedStatus);
//	SetStatus(ReloadingStatus);

	weaponColor.red = 1.0f;
	weaponColor.green = 0.0f;
	weaponColor.blue = 0.0f;
}

// MSL 5.03 RTX
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIWeapon::SetJamCount(Scalar new_count)
{
	Check_Object(this);
	
	weaponJamCount = new_count;
}

// MSL 5.03 Ammo Bay Fire
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIWeapon::SetFireCount(Scalar new_count)
{
	Check_Object(this);
	
	weaponFireCount = new_count;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIWeapon::SetCount(Scalar new_count)
{
	Check_Object(this);
	
	weaponCount = new_count;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIWeapon::Ready()
{
	Check_Object(this);
	
	SetStatus(ReadyStatus);
	weaponColor.red = readyColor.red;
	weaponColor.green = readyColor.green;
	weaponColor.blue = readyColor.blue;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIWeapon::Select()
{
	Check_Object(this);
	
	readyColor.red = 0.0f;
	readyColor.green = 1.0f;
	readyColor.blue = 0.0f;

}

//#######################################################################
//###########################    GUIWeaponManager   #####################
//#######################################################################

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUIWeaponManager::GUIWeaponManager() :
	Plug(Plug::DefaultData),
	weaponList(NULL)
{
	SPEW(("daberger", "Weapon Font should be set not hard coded"));
//	weaponFontHandle = gos_LoadFont("Assets\\Graphics\\arial8.tga", 0);
	guiManager = NULL;

	Initialize_Timer(Weapon_Text_Draw, "Weapon Text Draw");
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUIWeaponManager::~GUIWeaponManager()
{
	weaponList.DeletePlugs();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
GUIWeapon*
	GUIWeaponManager::MakeGUIWeapon(
		const char *weapon_name,
		Scalar weapon_count,
		RGBAColor *weapon_color,
		int *ammo_count,
		Weapon *owning_weapon
	)
{
	Check_Object(this);
	Check_Pointer(weapon_name);
	Check_Pointer(weapon_color);

	GUIWeapon *weapon =
		new GUIWeapon(weapon_name, weapon_count, weapon_color, ammo_count, owning_weapon);
	Check_Object(weapon);
	weaponList.Add(weapon);
	return weapon;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIWeaponManager::ChangeGroup(GUIWeapon *weapon)
{
	Check_Object(this);
	Check_Object(weapon);
	
	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIWeaponManager::ClearWeaponsManager()
{
	Check_Object(this);

	weaponList.DeletePlugs();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	GUIWeaponManager::Draw()
{
#if 0
	Check_Object(this);

	//
	//----------------------------------------
	//This is the draw routine for the weapons
	//----------------------------------------
	//
	switch(drawMode)
	{
	case VehicleInterface::ChainFireMode:
	case VehicleInterface::SingleFireMode:
		{
			char text_string[128];

			if(drawMode == VehicleInterface::ChainFireMode)
				sprintf(text_string, "/color=%8xChain Fire Mode", 0xff00ff00);
			else
				sprintf(text_string, "/color=%8xSingle Fire Mode", 0xff00ff00);

			int chain_size;
			ChainIteratorOf<GUIWeapon *> iterator(&weaponList);
			chain_size = iterator.GetSize();

			if(chain_size == 0)
			{
				return;
			}
			
			gos_SetRenderState( gos_State_Texture, 0 );
			gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha );
			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];
			memset(quad_verticies, 0, sizeof(quad_verticies));
			int y_size = ((int)chain_size + 1) * 15;
			Max_Clamp(y_size, Environment.screenHeight);
			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		= (0.76f * Environment.screenWidth);
			quad_verticies[0].y		= 10.0f;
			quad_verticies[0].z		= 0.9f;
			quad_verticies[0].argb	= 0x77000000;

			quad_verticies[1].x		= (0.98f * Environment.screenWidth);
			quad_verticies[1].y		= 10.0f;
			quad_verticies[1].z		= 0.9f;
			quad_verticies[1].argb	= 0x77000000;

			quad_verticies[2].x		= (0.98f * Environment.screenWidth);
			quad_verticies[2].y		= y_position;
			quad_verticies[2].z		= 0.9f;
			quad_verticies[2].argb	= 0x77000000;

			quad_verticies[3].x		= (0.76f * Environment.screenWidth);
			quad_verticies[3].y		= y_position;
			quad_verticies[3].z		= 0.9f;
			quad_verticies[3].argb	= 0x77000000;

			gos_DrawQuads(quad_verticies, 4);

			//Second we need to set up all of the String Attributes
			gos_TextSetRegion(
				(int)(0.72f * Environment.screenWidth),
				10,
				(int)(0.98f * Environment.screenWidth),
				(int)y_position
			);

			gos_TextSetAttributes(
					weaponFontHandle,
					0xffffffff,
					1.0f,
					false,
					true,
					false,
					false
				);

			GUIWeapon *gui_weapon;
			int count = 1;
			//
			//-----------------------------------------
			//Write out the group number that we are in
			//-----------------------------------------
			//
			int y_location = (count * 15) + 5;	
			gos_TextSetPosition((int)(0.77f * Environment.screenWidth), y_location);
			Start_Timer(Weapon_Text_Draw);
			gos_TextDraw(text_string);
			Stop_Timer(Weapon_Text_Draw);
			count = 2;
			while(((gui_weapon = iterator.ReadAndNext()) != NULL) &&
				(count <= 23))
			{
				Check_Object(gui_weapon);
				y_location = (count * 15) + 5;
				
				gos_TextSetPosition((int)(0.77f * Environment.screenWidth), y_location);
				Start_Timer(Weapon_Text_Draw);
				gui_weapon->Draw(y_location);
				Stop_Timer(Weapon_Text_Draw);
				count ++;
			}
			break;
		}
	case VehicleInterface::GroupFireMode:
		{
			ChainIteratorOf<Weapon *> *iterator;
			char text_string[128];
	
			if (NULL == guiManager->vehicleInterface)
				return;
			switch(guiManager->vehicleInterface->selectedWeaponGroup)
			{
			case 1:
				iterator = new ChainIteratorOf<Weapon *>(&guiManager->vehicleInterface->weaponGroup1);
				sprintf(text_string, "/color=%8xWeapon Group 1", 0xff00ff00);
				break;
			case 2:
				iterator = new ChainIteratorOf<Weapon *>(&guiManager->vehicleInterface->weaponGroup2);
				sprintf(text_string, "/color=%8xWeapon Group 2", 0xff00ff00);
				break;
			case 3:
				iterator = new ChainIteratorOf<Weapon *>(&guiManager->vehicleInterface->weaponGroup3);
				sprintf(text_string, "/color=%8xWeapon Group 3", 0xff00ff00);
				break;
			case 4:
				iterator = new ChainIteratorOf<Weapon *>(&guiManager->vehicleInterface->weaponGroup4);
				sprintf(text_string, "/color=%8xWeapon Group 4", 0xff00ff00);
				break;
			case 5:
				iterator = new ChainIteratorOf<Weapon *>(&guiManager->vehicleInterface->weaponGroup5);
				sprintf(text_string, "/color=%8xWeapon Group 5", 0xff00ff00);
				break;
			default:
				return;
			}
			
			int chain_size = iterator->GetSize();

			if(chain_size == 0)
			{
				return;
			}
			
			gos_SetRenderState( gos_State_Texture, 0 );
			gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha );
			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];
			memset(quad_verticies, 0, sizeof(quad_verticies));
			int y_size = ((int)chain_size + 1) * 15;
			Max_Clamp(y_size, Environment.screenHeight);
			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		= (0.76f * Environment.screenWidth);
			quad_verticies[0].y		= 10.0f;
			quad_verticies[0].z		= 0.9f;
			quad_verticies[0].argb	= 0x77000000;

			quad_verticies[1].x		= (0.98f * Environment.screenWidth);
			quad_verticies[1].y		= 10.0f;
			quad_verticies[1].z		= 0.9f;
			quad_verticies[1].argb	= 0x77000000;

			quad_verticies[2].x		= (0.98f * Environment.screenWidth);
			quad_verticies[2].y		= y_position;
			quad_verticies[2].z		= 0.9f;
			quad_verticies[2].argb	= 0x77000000;

			quad_verticies[3].x		= (0.76f * Environment.screenWidth);
			quad_verticies[3].y		= y_position;
			quad_verticies[3].z		= 0.9f;
			quad_verticies[3].argb	= 0x77000000;

			gos_DrawQuads(quad_verticies, 4);

			//Second we need to set up all of the String Attributes
			gos_TextSetRegion(
				(int)(0.72f * Environment.screenWidth),
				10,
				(int)(0.98f * Environment.screenWidth),
				(int)y_position
			);

			gos_TextSetAttributes(
					weaponFontHandle,
					0xffffffff,
					1.0f,
					false,
					true,
					false,
					false
				);

			Weapon *weapon;
			int count = 1;
			//
			//-----------------------------------------
			//Write out the group number that we are in
			//-----------------------------------------
			//
			int y_location = (count * 15) + 5;	
			gos_TextSetPosition((int)(0.77f * Environment.screenWidth), y_location);
			Start_Timer(Weapon_Text_Draw);
			gos_TextDraw(text_string);
			Stop_Timer(Weapon_Text_Draw);
			count = 2;
			while(((weapon = iterator->ReadAndNext()) != NULL) &&
				(count <= 23))
			{
				Check_Object(weapon);
				if(weapon->guiWeapon.GetCurrent())
				{
					y_location = (count * 15) + 5;
				
					gos_TextSetPosition((int)(0.77f * Environment.screenWidth), y_location);
					Start_Timer(Weapon_Text_Draw);
					weapon->guiWeapon.GetCurrent()->Draw(y_location);
					Stop_Timer(Weapon_Text_Draw);
					count ++;
				}
			}
			delete iterator;
			break;
		}
	}
#endif
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int GUIWeaponManager::GetWeaponInfo (char **name_array, int *status,int *ammo,Stuff::Scalar *reloads,Stuff::Scalar *current_time,int *group_1,int *group_2,int *group_3, int *group_4,int *group_5,int *group_6,int *num_weapons, int array_size)
{
	ChainIteratorOf<GUIWeapon *> iterator(&weaponList);
	GUIWeapon *weapon;
	int i = 0;
	while(((weapon = iterator.ReadAndNext()) != NULL) &&
		(i < array_size))
	{
		Check_Object(weapon);
		FREEANDNULL(name_array[i]);
		name_array[i] = (char *)gos_Malloc(128);
		Str_Copy(
			name_array[i],
			(const char *)weapon->weaponName,
			(strlen(weapon->weaponName) + 1)
		);
		ammo[i] = DECRYPT(*weapon->ammoCount);
		status[i] = weapon->m_status;
		if(weapon->m_weapon)
		{
			const Weapon::GameModel *weapon_model = weapon->m_weapon->GetGameModel();
			Check_Object(weapon_model);

			reloads[i] = weapon_model->reloadTime;
			group_1[i] = weapon->m_weapon->IsInWeaponGroup1();
			group_2[i] = weapon->m_weapon->IsInWeaponGroup2();
			group_3[i] = weapon->m_weapon->IsInWeaponGroup3();
			group_4[i] = weapon->m_weapon->IsInWeaponGroup4();
			group_5[i] = weapon->m_weapon->IsInWeaponGroup5();
			group_6[i] = 0;
		}
		else
		{
			reloads[i] = 0.0f;
			group_1[i] = 0;
			group_2[i] = 0;
			group_3[i] = 0;
			group_4[i] = 0;
			group_5[i] = 0;
			group_6[i] = 0;
		}

		current_time[i] = weapon->weaponCount;
		i++;
	}
	*num_weapons = i;	

	return 1;
}

