//========= Copyright © 1996-2005, Sander Corporation, All rights reserved. ============//
//
// Purpose: hud_rts_unitpanel.cpp
//
// $NoKeywords: $
//=============================================================================//

#include "cbase.h"
#include "hl2wars/hud_rts_abilitypanel.h"
#include <vgui/ISurface.h>
#include "hl2wars/in_buttons_rts.h"
#include <KeyValues.h>
#include "c_ai_basenpc.h"
#include "hl2wars/c_rts_buildings.h"
#include "hl2wars/c_rts_globalresource.h"
#include "hl2wars/c_hl2wars_player.h"
#include "hl2wars/rts_parsedata.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

using namespace vgui;

//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CHudRTSAbilityPanel::CHudRTSAbilityPanel( ) : BaseClass( NULL, "AbilityPanel" )// : vgui::Panel( NULL, "AbilityPanel" )
{
	SetProportional( true );
	SetPaintBackgroundEnabled( false );
	SetKeyBoardInputEnabled( false );	
	SetMouseInputEnabled( true );	
	SetScheme("ClientScheme.res");

	m_iLastHighLightedUnit = -2;
	m_iLastHighLightedAbility = -1;
	m_iLastSelectedAbility = -1;

	m_bActive = false;

	for( int i = 0; i < MAX_TEAMS_ID_RTS; i++ )
		m_AbilityStates[i].SetLessFunc( DefLessFunc( unsigned short ) );
}

//-----------------------------------------------------------------------------
// Purpose: Deconstructor
//-----------------------------------------------------------------------------
CHudRTSAbilityPanel::~CHudRTSAbilityPanel()
{

}

void CHudRTSAbilityPanel::Init( void )
{
	SetCursor( GetParent()->GetCursor() );

	m_pAbility[0] = new CBitmapButtonRTS( this, "ability_slot1", NULL);
	CreateButtonAbility( m_pAbility[0], "ability_slot1");
	m_pAbility[1] = new CBitmapButtonRTS( this, "ability_slot2", NULL);
	CreateButtonAbility( m_pAbility[1], "ability_slot2");
	m_pAbility[2] = new CBitmapButtonRTS( this, "ability_slot3", NULL);
	CreateButtonAbility( m_pAbility[2], "ability_slot3");
	m_pAbility[3] = new CBitmapButtonRTS( this, "ability_slot4", NULL);
	CreateButtonAbility( m_pAbility[3], "ability_slot4");

	m_pAbility[4] = new CBitmapButtonRTS( this, "ability_slot5", NULL);
	CreateButtonAbility( m_pAbility[4], "ability_slot5");
	m_pAbility[5] = new CBitmapButtonRTS( this, "ability_slot6", NULL);
	CreateButtonAbility( m_pAbility[5], "ability_slot6");
	m_pAbility[6] = new CBitmapButtonRTS( this, "ability_slot7", NULL);
	CreateButtonAbility( m_pAbility[6], "ability_slot7");
	m_pAbility[7] = new CBitmapButtonRTS( this, "ability_slot8", NULL);
	CreateButtonAbility( m_pAbility[7], "ability_slot8");

	m_pAbility[8] = new CBitmapButtonRTS( this, "ability_slot9", NULL);
	CreateButtonAbility( m_pAbility[8], "ability_slot9");
	m_pAbility[9] = new CBitmapButtonRTS( this, "ability_slot10", NULL);
	CreateButtonAbility( m_pAbility[9], "ability_slot10");
	m_pAbility[10] = new CBitmapButtonRTS( this, "ability_slot11", NULL);
	CreateButtonAbility( m_pAbility[10], "ability_slot11");
	m_pAbility[11] = new CBitmapButtonRTS( this, "ability_slot12", NULL);
	CreateButtonAbility( m_pAbility[11], "ability_slot12");

	// find the info panel
	CHudElement *pEl = gHUD.FindElement( "CHudRTSInfoPanel" );
	if( pEl )
	{
		CHudRTSInfoPanel *pHIP = dynamic_cast<CHudRTSInfoPanel *>(pEl);
		if( pHIP )
		{
			SetInfoPanel( pHIP );
		}
	}

	// set active
	m_bActive = true;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
//void CHudRTSAbilityPanel::LevelShutdown( void )
//{
//
//}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CHudRTSAbilityPanel::OnThink( void )
{
	if ( NeedsUpdate() )
	{
		Update();
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CHudRTSAbilityPanel::Update()
{
	C_HL2Wars_Player* pPlayer = C_HL2Wars_Player::GetLocalHL2WarsPlayer();
	if( !pPlayer ) 
		return;

	color32 color;
	color.r = color.g = color.b = color.a = 1.0f;

	// check what we need to update
	switch( pPlayer->GetSelectionType() ) {
		case SELECTION_UNIT:
			{
				// update ability images of the units, and store the current state
				for( int i = 1; i < 13; i++ ) 
				{
					int abilityType = GetAbilityType( i );
					int abilityhandle = GetAbilityHandle( i );
					if( pPlayer->GetSelectedAbility() == i && abilityType != ABILITY_NONE ) 
					{
						m_iLastSelectedAbility = i;
						m_pAbility[i - 1]->AddButtonFlags( F_SELECTED );
					}
					else
						m_pAbility[i - 1]->RemoveButtonFlags( F_SELECTED );

					int time = GetRechargeTime( i );
					if( abilityType == 0 )
					{
						m_pAbility[ i - 1 ]->SetVisible( false );
					}
					else if( !IsAbilityAvailable( pPlayer->GetTeamRTSID(), abilityhandle ) )
					{
						m_pAbility[i - 1]->SetEnabled( false );
						m_pAbility[i - 1]->RemoveButtonFlags( F_SHOWPROGRESS );
						m_pAbility[ i - 1 ]->SetVisible( true );
						DrawAbilityImage( GetImage(i, m_pAbility[i - 1]->IsEnabled()), i, abilityhandle, 
							INFOTYPE_ABILITY, color );						
					}
					else if( time > gpGlobals->curtime ) 
					{
						m_pAbility[i - 1]->SetEnabled( false );
						m_pAbility[ i - 1 ]->SetVisible( true );
						float weight = ( time - gpGlobals->curtime ) / GetMaxAbilityTime( i );
						m_pAbility[i - 1]->SetProgress( weight );
						m_pAbility[i - 1]->AddButtonFlags( F_SHOWPROGRESS );
						DrawAbilityImage( GetImage(i, m_pAbility[i - 1]->IsEnabled() ), i, abilityhandle, 
							INFOTYPE_ABILITY, color );	
					}
					else 
					{
						m_pAbility[i - 1]->SetEnabled( true );
						m_pAbility[i - 1]->RemoveButtonFlags( F_SHOWPROGRESS );
						m_pAbility[ i - 1 ]->SetVisible( true );
						DrawAbilityImage( GetImage(i, m_pAbility[i - 1]->IsEnabled()), i, abilityhandle, 
							INFOTYPE_ABILITY, color );
					}
				}	
				m_iLastHighlightedUnit = GetUnitIndex();
				m_pLastSelectedBuilding = NULL;
				if( pPlayer->GetSelectedAbility() != m_iLastSelectedAbility )
					m_iLastHighlightedUnit = -1;
			}
			break;
		case SELECTION_BUILDING:
			{
				// update ability/build images of the building, and store the current state
				if( pPlayer->GetSelectedBuilding() )
				{
					if( pPlayer->GetSelectedBuilding()->IsRTSBrush() )
					{
						C_BuildingBrush *pSelected = dynamic_cast<C_BuildingBrush *>( pPlayer->GetSelectedBuilding() );
						if( pSelected )
						{
							for( int i = 1; i < 13; i++ ) 
							{
								int unit_index = pSelected->GetUnitIndexBuild( i );
								if( unit_index == 0 )
								{
									m_pAbility[ i - 1 ]->SetVisible( false );
								}
								else
								{
									m_pAbility[ i - 1 ]->SetEnabled( true );
									m_pAbility[ i - 1 ]->SetVisible( true );
									m_pAbility[ i - 1 ]->RemoveButtonFlags( F_SELECTED );
									m_pAbility[ i - 1 ]->RemoveButtonFlags( F_SHOWPROGRESS );
									DrawAbilityImage( m_pUnitPanel->GetImage( pSelected->GetUnitType( unit_index ) ), i,
										unit_index, INFOTYPE_BUILDING, color  );
								}
							}

							m_pLastSelectedBuilding = pSelected;
							m_iLastHighlightedUnit = -1;
						}
					}
					else if( pPlayer->GetSelectedBuilding()->IsRTSModel() )
					{
						C_BaseBuildingModel *pSelectedM = dynamic_cast<C_BaseBuildingModel *>( pPlayer->GetSelectedBuilding() );
						if( pSelectedM && pSelectedM->IsAlive() ) {
							for( int i = 1; i < 13; i++ ) 
							{
								int unit_index = pSelectedM->GetTypeAbility( i );
								if( unit_index == 0 )
								{
									m_pAbility[ i - 1 ]->SetVisible( false );
								}
								else
								{
									m_pAbility [i - 1 ]->SetEnabled( true );
									m_pAbility[ i - 1 ]->SetVisible( true );
									m_pAbility[ i - 1 ]->RemoveButtonFlags( F_SELECTED );
									m_pAbility[ i - 1 ]->RemoveButtonFlags( F_SHOWPROGRESS );
									DrawAbilityImage( m_pUnitPanel->GetImage( g_RTSR->GetUnitType( unit_index ) ), i,
										unit_index, INFOTYPE_BUILDING, color  );
								}
							}

							m_pLastSelectedBuilding = pSelectedM;
							m_iLastHighlightedUnit = -1;
						}
					}
				}
			}
			break;
		default:
			break;
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CHudRTSAbilityPanel::NeedsUpdate( void )
{
	C_HL2Wars_Player* pPlayer = C_HL2Wars_Player::GetLocalHL2WarsPlayer();
	if( !pPlayer ) 
		return false;

	// check the kind of selection and check if the current state has changed since the last update
	switch( pPlayer->GetSelectionType() ) {
		case SELECTION_UNIT:
			{
				if( GetUnitIndex() != m_iLastHighlightedUnit ||
						pPlayer->GetSelectedAbility() != m_iLastSelectedAbility ||
						CheckArmedButtons() )
					return true;
			}
			break;
		case SELECTION_BUILDING:
			{
				if( m_pLastSelectedBuilding != pPlayer->GetSelectedBuilding() || CheckArmedButtons() )
					return true;
			}
			break;
		default:
			break;
	}

	return false;
}

//-----------------------------------------------------------------------------
// Purpose: Checks for buttons that are armed
//-----------------------------------------------------------------------------
bool CHudRTSAbilityPanel::CheckArmedButtons()
{
	for( int i = 0; i < MAXABILITIESSLOTS; i++ ) {
		if( m_pAbility[i]->IsArmed() )
			return true;
	}

	return false;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
BitmapImage *CHudRTSAbilityPanel::GetImage( int i, bool enabled )
{
	FileUnitInfo_t *pFUI = GetFileUnitInfoFromHandle( LookupUnitInfoSlot( GetUnitType() ) );
	if( !pFUI )
		return NULL;

	FileAbilityInfo_t *pFAI = GetFileAbilityInfoFromHandle( pFUI->m_iAbilities[i-1] );
	if( !pFAI )
		return NULL;

	if( enabled )
		return pFAI->m_pImage;
	else
		return pFAI->m_pImageDis;
}

//-----------------------------------------------------------------------------
// Purpose: Draw selected units and abilties
//-----------------------------------------------------------------------------
void CHudRTSAbilityPanel::DrawAbilityImage( BitmapImage *image, int slot, int type, int infotype, color32 color ) 
{
	if( m_pAbility[slot - 1]->IsEnabled() )
		m_pAbility[slot - 1]->SetImage( CBitmapButtonRTS::BUTTON_ENABLED, image, color);
	else
		m_pAbility[slot - 1]->SetImage( CBitmapButtonRTS::BUTTON_DISABLED, image, color);

	if( m_pAbility[slot - 1]->IsArmedIgnoredEnabled() && type != 0 ) {
		m_pInfoPanel->SetType( type );
		m_pInfoPanel->SetInfoType( infotype );
		m_pInfoPanel->SetTimeOut( gpGlobals->curtime + 1.0f );
		m_pInfoPanel->SetVisible( true );
	}
}

//-----------------------------------------------------------------------------
// Purpose: Create button template
//-----------------------------------------------------------------------------
void CHudRTSAbilityPanel::CreateButtonAbility( CBitmapButtonRTS *pSlot, const char *command) 
{
    pSlot->SetVisible( true );
	pSlot->SetPaintBackgroundEnabled( false );
	pSlot->SetPaintBorderEnabled( false );
	pSlot->SetParent(this);
	pSlot->AddActionSignalTarget(this);
	pSlot->SetCommand(command);
	pSlot->SetHighLightImages( "VGUI/button_hover", "VGUI/button_selected" );
	pSlot->AddButtonFlags( F_ONEIMAGE );
}

void CHudRTSAbilityPanel::CalculateSizePos( void )
{
	int xmax, ymax;
	GetSize( xmax, ymax );

	int sizex = (int)(xmax / 4.0);
	int sizey = (int)(ymax / 3.0);

	// we will fill the buttons in a square of 4x3
	int delta = (int)( xmax / 4 );
	int delta_y = (int)( ymax / 3 );

	m_pAbility[0]->SetSize( sizex, sizey );
	m_pAbility[1]->SetSize( sizex, sizey );
	m_pAbility[2]->SetSize( sizex, sizey );
	m_pAbility[3]->SetSize( sizex, sizey );
	m_pAbility[4]->SetSize( sizex, sizey );
	m_pAbility[5]->SetSize( sizex, sizey );
	m_pAbility[6]->SetSize( sizex, sizey );
	m_pAbility[7]->SetSize( sizex, sizey );
	m_pAbility[8]->SetSize( sizex, sizey );
	m_pAbility[9]->SetSize( sizex, sizey );
	m_pAbility[10]->SetSize( sizex, sizey );
	m_pAbility[11]->SetSize( sizex, sizey );

	m_pAbility[0]->SetPos( 0, 0 );
	m_pAbility[1]->SetPos( delta, 0 );
	m_pAbility[2]->SetPos( delta * 2, 0 );
	m_pAbility[3]->SetPos( delta * 3, 0 );

	m_pAbility[4]->SetPos( 0, delta_y );
	m_pAbility[5]->SetPos( delta, delta_y );
	m_pAbility[6]->SetPos( delta * 2, delta_y );
	m_pAbility[7]->SetPos( delta * 3, delta_y );

	m_pAbility[8]->SetPos( 0, delta_y * 2 );
	m_pAbility[9]->SetPos( delta, delta_y * 2 );
	m_pAbility[10]->SetPos( delta * 2, delta_y * 2 );
	m_pAbility[11]->SetPos( delta * 3, delta_y * 2 );
}

//-----------------------------------------------------------------------------
// Purpose: Handles the button presses of the unit slots
//-----------------------------------------------------------------------------
void CHudRTSAbilityPanel::OnCommand(const char *command) 
{ 
	C_HL2Wars_Player* pPlayer = C_HL2Wars_Player::GetLocalHL2WarsPlayer();
	if( !pPlayer ) 
		return;

	int *m_nNewRTSCommands = pPlayer->GetRTSCommands();
	if (!stricmp(command, "ability_slot1")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_1;
	} 
	else if (!stricmp(command, "ability_slot2")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_2;
	} 
	else if (!stricmp(command, "ability_slot3")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_3;
	} 
	else if (!stricmp(command, "ability_slot4")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_4;
	} 
	else if (!stricmp(command, "ability_slot5")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_5;
	} 
	else if (!stricmp(command, "ability_slot6")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_6;
	} 
	else if (!stricmp(command, "ability_slot7")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_7;
	} 
	else if (!stricmp(command, "ability_slot8")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_8;
	} 
	else if (!stricmp(command, "ability_slot9")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_9;
	} 
	else if (!stricmp(command, "ability_slot10")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_10;
	} 
	else if (!stricmp(command, "ability_slot11")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_11;
	} 
	else if (!stricmp(command, "ability_slot12")) 
	{ 
		*m_nNewRTSCommands |= IN_ABILITY_12;
	} 

	BaseClass::OnCommand(command);   
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
const char *CHudRTSAbilityPanel::GetUnitType( void ) 
{  
	C_HL2Wars_Player* pPlayer = C_HL2Wars_Player::GetLocalHL2WarsPlayer();
	if( !pPlayer ) 
		return "UNIT_NONE";

	if( pPlayer->m_HLWLocal.m_hSelectedUnits[ pPlayer->GetHighLightedUnit() ] )
		return g_RTSR->GetUnitType(pPlayer->m_HLWLocal.m_hSelectedUnits[ pPlayer->GetHighLightedUnit() ].Get()->GetUnitIndex());
	else
		return "UNIT_NONE";
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CHudRTSAbilityPanel::GetUnitIndex( void )
{
	C_HL2Wars_Player* pPlayer = C_HL2Wars_Player::GetLocalHL2WarsPlayer();
	if( !pPlayer ) 
		return 0;

	if( pPlayer->m_HLWLocal.m_hSelectedUnits[ pPlayer->GetHighLightedUnit() ] )
		return pPlayer->m_HLWLocal.m_hSelectedUnits[ pPlayer->GetHighLightedUnit() ].Get()->GetUnitIndex();
	else
		return 0;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CHudRTSAbilityPanel::GetRechargeTime( int ability )
{
	C_HL2Wars_Player* pPlayer = C_HL2Wars_Player::GetLocalHL2WarsPlayer();
	if( !pPlayer ) 
		return -1.0f;

	int unitIndex = pPlayer->GetHighLightedUnit();
	if( pPlayer->m_HLWLocal.m_hSelectedUnits[unitIndex] ) 
	{
		return pPlayer->m_HLWLocal.m_hSelectedUnits[unitIndex]->GetRechargeTime( ability - 1 );
	}
	else
		return -1.0f;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CHudRTSAbilityPanel::GetMaxAbilityTime( int ability_button )
{
	FileUnitInfo_t *pFUI = GetFileUnitInfoFromHandle( LookupUnitInfoSlot( GetUnitType() ) );
	if( !pFUI )
		return 0.0f;

	FileAbilityInfo_t *pFAI = GetFileAbilityInfoFromHandle( pFUI->m_iAbilities[ability_button-1] );
	if( !pFAI )
		return 0.0f;

	return pFAI->m_iRechargeTime;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CHudRTSAbilityPanel::GetAbilityType( int i )
{
	FileUnitInfo_t *pFUI = GetFileUnitInfoFromHandle( LookupUnitInfoSlot( STRING( GetUnitType() ) ) );
	if( !pFUI )
		return 1;

	FileAbilityInfo_t *pFAI = GetFileAbilityInfoFromHandle( pFUI->m_iAbilities[i-1] );
	if( !pFAI )
		return 1;

	return pFAI->m_iAbilityType;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CHudRTSAbilityPanel::GetAbilityHandle( int i )
{
	FileUnitInfo_t *pFUI = GetFileUnitInfoFromHandle( LookupUnitInfoSlot( STRING( GetUnitType() ) ) );
	if( !pFUI )
		return 1;

	return pFUI->m_iAbilities[i-1];
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudRTSAbilityPanel::SetUnitPanel( CHudRTSUnitPanel *pUnitPanel )
{
	m_pUnitPanel = pUnitPanel;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudRTSAbilityPanel::SetInfoPanel( CHudRTSInfoPanel *pInfoPanel )
{
	m_pInfoPanel = pInfoPanel;
}

void CHudRTSAbilityPanel::OnMousePressed(MouseCode code)
{
	if( GetParent() )	// let our parent handle this
		GetParent()->OnMousePressed( code );
}

void CHudRTSAbilityPanel::OnMouseReleased(MouseCode code)
{
	if( GetParent() )	// let our parent handle this
		GetParent()->OnMouseReleased( code );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CHudRTSAbilityPanel::IsAbilityAvailable( int teamid, ABILITY_FILE_INFO_HANDLE handle )
{
	// first, find the entry
	int index;
	if( m_AbilityStates[teamid-DEFAULT_TEAMS].IsValidIndex( index = m_AbilityStates[teamid-DEFAULT_TEAMS].Find(handle) ) )
	{
		return m_AbilityStates[teamid-DEFAULT_TEAMS].Element(index).m_bAvailable;
	}
	else
	{
		// No entry yet. Means this one is available, since the tech tree didn't do anything with it.
		//NewAbilityState(teamid, true, true, 0, handle );

		return true;
	}	
}

//-----------------------------------------------------------------------------
// Purpose: 
// Input  : 
//-----------------------------------------------------------------------------
void CHudRTSAbilityPanel::AbilityStateUpdate( bf_read &msg )
{
	char name[255];
	int type, teamid;
	unsigned short handle;

	type = msg.ReadByte();
	teamid = msg.ReadByte();
	msg.ReadString( name, 255 );
	handle = LookupAbilityInfoSlot(name);
	
	//Msg("Receiving message %d from server about ability states, type %d\n", handle, type );

	switch( type )
	{
	case AS_NEW:
		{
			ability_state_t entry;
			entry.m_bAvailable = msg.ReadByte();
			entry.m_bOverridable = msg.ReadByte();
			entry.m_iCount = msg.ReadByte();

			m_AbilityStates[teamid-DEFAULT_TEAMS].Insert(handle, entry);	
		}
		break;
	case AS_MSTATE:
		{
			int index;
			if( m_AbilityStates[teamid-DEFAULT_TEAMS].IsValidIndex( index = m_AbilityStates[teamid-DEFAULT_TEAMS].Find(handle) ) )
			{
				m_AbilityStates[teamid-DEFAULT_TEAMS].Element(index).m_bAvailable = msg.ReadByte();
			}
		}
		break;
	case AS_MCOUNT:
		{
			int index;
			if( m_AbilityStates[teamid-DEFAULT_TEAMS].IsValidIndex( index = m_AbilityStates[teamid-DEFAULT_TEAMS].Find(handle) ) )
			{
				m_AbilityStates[teamid-DEFAULT_TEAMS].Element(index).m_iCount = msg.ReadByte();
			}
		}
		break;
	}
}