/*
**	Command & Conquer Renegade(tm)
**	Copyright 2025 Electronic Arts Inc.
**
**	This program is free software: you can redistribute it and/or modify
**	it under the terms of the GNU General Public License as published by
**	the Free Software Foundation, either version 3 of the License, or
**	(at your option) any later version.
**
**	This program is distributed in the hope that it will be useful,
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**	GNU General Public License for more details.
**
**	You should have received a copy of the GNU General Public License
**	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/******************************************************************************
*
* FILE
*     $Archive: /Commando/Code/Commando/DlgMPTeamSelect.cpp $
*
* DESCRIPTION
*     Multiplayer team selection dialog.
*
* PROGRAMMER
*     Denzil E. Long, Jr.
*     $Author: Denzil_l $
*
* VERSION INFO
*     $Revision: 17 $
*     $Modtime: 2/24/02 2:51p $
*
******************************************************************************/

#include "dlgmpteamselect.h"
#include "wolgmode.h"
#include "gamedata.h"
#include "wolgameinfo.h"
#include "wolloginprofile.h"
#include "dlgmessagebox.h"
#include "renegadedialogmgr.h"
#include <combat\playertype.h>
#include <wwonline\wolgameoptions.h>
#include <wwui\listctrl.h>
#include <wwui\comboboxctrl.h>
#include <wwui\imagectrl.h>
#include "resource.h"
#include "string_ids.h"
#include <wwtranslatedb\translatedb.h>
#include "modpackagemgr.h"
#include "gameinitmgr.h"


using namespace WWOnline;


// Player list columns
enum
	{
	COL_RANK,
	COL_NAME,
// Denzil 02/24/02 Day 1 patch - Remove clan until we can fix formating
//	COL_CLAN,
	COL_KD,
	COL_SCORE
	};


// Private game options processing dispatching
typedef void (*GameOptionsDispatchFunc)(DlgMPTeamSelect&, const char*);

#define PARSE_INT(s, d, v) {char* ptr = strtok(s, d); if (ptr) {v = atoi(ptr);}}
#define PARSE_FLOAT(s, d, v) {char* ptr = strtok(s, d); if (ptr) {v = atof(ptr);}}
#define PARSE_HEXDWORD(s, d, v) {char* ptr = strtok(s, d); if (ptr) {sscanf(ptr, "%08X", &v);}}
#define PARSE_HEXBYTE(s, d, v) {char* ptr = strtok(s, d); if (ptr) {sscanf(ptr, "%02X", &v);}}
#define PARSE_STRING(s, d, v) {v = strtok(s, d);}


static int CALLBACK ListSortCallback(ListCtrlClass* list, int index1, int index2, uint32 param)
	{
	int rank1 = (int)list->Get_Entry_Data(index1, COL_RANK);
	int rank2 = (int)list->Get_Entry_Data(index2, COL_RANK);
	return (rank1 - rank2);
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::DoDialog
*
* DESCRIPTION
*     Display team selection / team profile dialog
*
* INPUTS
*     Target - Target to receive user choice signal.
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::DoDialog(Signaler<MPChooseTeamSignal>& target)
	{
	DlgMPTeamSelect* dialog = new DlgMPTeamSelect;

	if (dialog)
		{
		if (dialog->FinalizeCreate())
			{
			dialog->Start_Dialog();
			dialog->SignalMe(target);
			}

		dialog->Release_Ref();
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::DlgMpTeamSelect
*
* DESCRIPTION
*     Constructor
*
* INPUTS
*     NONE
*
* RESULT
*     NONE
*
******************************************************************************/

DlgMPTeamSelect::DlgMPTeamSelect(void) :
		MenuDialogClass(IDD_MP_TEAM_SELECT),
		mWOLGame(true),
		mCanChoose(true),
		mTimeRemaining(0.0f)
	{
	WWDEBUG_SAY(("DlgMPTeamSelect instantiated\n"));
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::~DlgMPTeamSelect
*
* DESCRIPTION
*     Destructor
*
* INPUTS
*     NONE
*
* RESULT
*     NONE
*
******************************************************************************/

DlgMPTeamSelect::~DlgMPTeamSelect()
	{
	WWDEBUG_SAY(("DlgMPTeamSelect destroyed\n"));
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::FinalizeCreate
*
* DESCRIPTION
*     Post creation initialization.
*
* INPUTS
*     NONE
*
* RESULT
*     True if successful
*
******************************************************************************/

bool DlgMPTeamSelect::FinalizeCreate(void)
	{
	GameModeClass* gameMode = GameModeManager::Find("WOL");

	if (gameMode && gameMode->Is_Active())
		{
		mWOLGame = true;
		mWOLSession = Session::GetInstance(false);

		// Cannot continue if WOL session is not initialized
		if (mWOLSession.IsValid() == false)
			{
			return false;
			}

		// Get the channel we have joined.
		const RefPtr<ChannelData>& channel = mWOLSession->GetCurrentChannel();

		// Cannot continue if we are not in a channel
		if (channel.IsValid() == false)
			{
			return false;
			}

		mGameInfo.ImportFromChannel(channel);

		Observer<ChannelEvent>::NotifyMe(*mWOLSession);
		Observer<UserEvent>::NotifyMe(*mWOLSession);
		}
	else
		{
		gameMode = GameModeManager::Find("LAN");

		if (gameMode && gameMode->Is_Active())
			{
			mWOLGame = false;
			mGameInfo.ImportFromGame(*The_Game());
			}
		}

	if (mGameInfo.IsDataValid() == false)
		{
		return false;
		}

	mCanChoose = (!mGameInfo.IsClanGame() && mGameInfo.IsTeamChange());

	return true;
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::On_Init_Dialog
*
* DESCRIPTION
*     One time dialog initialization
*
* INPUTS
*     NONE
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::On_Init_Dialog(void)
	{
	WWDEBUG_SAY(("DlgMPTeamSelect On_Init_Dialog\n"));

	MenuDialogClass::On_Init_Dialog();

	// Setup the team icons on the dialog
	((ImageCtrlClass*)Get_Dlg_Item(IDC_GDI_TEAM_ICON))->Set_Texture("HUD_C&C_GDILOGO.TGA");
	((ImageCtrlClass*)Get_Dlg_Item(IDC_NOD_TEAM_ICON))->Set_Texture("HUD_C&C_NODLOGO.TGA");

	// Setup the list controls
	ListCtrlClass* list = (ListCtrlClass*)Get_Dlg_Item(IDC_GDI_LIST_CTRL);

	if (list)
		{
		// Configure the columns
		list->Add_Column(TRANSLATE (IDS_MENU_RANK),  0.15F, Vector3(1, 1, 1));

// Denzil 02/24/02 Day 1 patch - Remove clan until we can fix formatting issues.
#if(0)
		list->Add_Column(TRANSLATE (IDS_MENU_NAME),  0.30F, Vector3(1, 1, 1));
		list->Add_Column(TRANSLATE (IDS_MENU_CLAN),  0.20F, Vector3(1, 1, 1));
#else
		list->Add_Column(TRANSLATE (IDS_MENU_NAME),  0.50F, Vector3(1, 1, 1));
#endif

		list->Add_Column(TRANSLATE (IDS_MENU_KD_RATIO),   0.15F, Vector3(1, 1, 1));
		list->Add_Column(TRANSLATE (IDS_MENU_SCORE), 0.20F, Vector3(1, 1, 1));
		}

	list = (ListCtrlClass*)Get_Dlg_Item(IDC_NOD_LIST_CTRL);

	if (list)
		{
		// Configure the columns
		list->Add_Column(TRANSLATE (IDS_MENU_RANK),  0.15F, Vector3(1, 1, 1));

// Denzil 02/24/02 Day 1 patch - Remove clan until we can fix formatting issues.
#if(0)
		list->Add_Column(TRANSLATE (IDS_MENU_NAME),  0.30F, Vector3(1, 1, 1));
		list->Add_Column(TRANSLATE (IDS_MENU_CLAN),  0.20F, Vector3(1, 1, 1));
#else
		list->Add_Column(TRANSLATE (IDS_MENU_NAME),  0.50F, Vector3(1, 1, 1));
#endif

		list->Add_Column(TRANSLATE (IDS_MENU_KD_RATIO),   0.15F, Vector3(1, 1, 1));
		list->Add_Column(TRANSLATE (IDS_MENU_SCORE), 0.20F, Vector3(1, 1, 1));		
		}

	int sidePref = -1;

	if (mWOLGame)
		{
		// If this is not a clan game then we can use the preference.
		if (mGameInfo.IsClanGame() == false)
			{
			const RefPtr<LoginInfo>& login = mWOLSession->GetCurrentLogin();
			WWASSERT(login.IsValid());
		
			LoginProfile* profile = LoginProfile::Get(login->GetNickname());
	
			if (profile)
				{
				sidePref = profile->GetSidePreference();
				profile->Release_Ref();
				}
			}
	
		// The start button is disabled until we hear from the host.
		Enable_Dlg_Item(IDC_STARTGAME, false);

		// Request information about the game.
		RequestWOLGameInfo();
		}
	else
		{
		sidePref = cNetInterface::Get_Side_Preference();

		// Hide and disable the back button for LAN games.
		DialogControlClass* ctrl = Get_Dlg_Item(IDCANCEL);
		WWASSERT(ctrl != NULL);
		ctrl->Show(false);
		ctrl->Enable(false);

		cPlayerManager::Add_Event_Observer(*this);

		PopulateWithLANPlayers();
		}

	InitSideChoice(sidePref);

	//	Activate the menu game mode (if necessary)
	GameModeClass* menuMode = GameModeManager::Find("Menu");

	if (menuMode && !menuMode->Is_Active())
		{
		menuMode->Activate();
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::On_Frame_Update
*
* DESCRIPTION
*
* INPUTS
*     NONE
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::On_Frame_Update(void)
	{
	if (mTimeRemaining >= WWMATH_EPSILON)
		{
		mTimeRemaining -= TimeManager::Get_Frame_Real_Seconds();
		ShowTimeRemaining(mTimeRemaining);
		}

	MenuDialogClass::On_Frame_Update();
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::On_Command
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::On_Command(int ctrlID, int message, DWORD param)
	{
	switch (ctrlID)
		{
		case IDCANCEL:
		case IDC_STARTGAME:
			{
			int side = GetSideChoice();
			MPChooseTeamSignal chooseSignal((IDC_STARTGAME == ctrlID), side);
			Signaler<MPChooseTeamSignal>::SendSignal(chooseSignal);
			End_Dialog();
			}
			break;

		case IDC_TEAM_AUTO_CHECK:
			SelectSideChoice(PLAYERTYPE_RENEGADE);
			break;

		case IDC_TEAM_GDI_CHECK:
			SelectSideChoice(PLAYERTYPE_GDI);
			break;

		case IDC_TEAM_NOD_CHECK:
			SelectSideChoice(PLAYERTYPE_NOD);
			break;
		}

	MenuDialogClass::On_Command(ctrlID, message, param);
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::On_Last_Menu_Ending
*
* DESCRIPTION
*     Callback from menu class signifying the close of the last menu
*
* INPUTS
*     NONE
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::On_Last_Menu_Ending(void)
	{
	// If this the WOL screen then return to the menu...
	if (GameInitMgrClass::Is_WOL_Initialized())
		{
		RenegadeDialogMgrClass::Goto_Location(RenegadeDialogMgrClass::LOC_INTERNET_GAME_LIST);
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::InitSideChoice
*
* DESCRIPTION
*
* INPUTS
*     NONE
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::InitSideChoice(int sidePref)
	{
	Enable_Dlg_Item(IDC_TEAM_AUTO_CHECK, mCanChoose);
	Enable_Dlg_Item(IDC_TEAM_GDI_CHECK, mCanChoose);
	Enable_Dlg_Item(IDC_TEAM_NOD_CHECK, mCanChoose);

	// Default side selection combo to the users preference.
	int side = ((mCanChoose == true) ? sidePref : -1);
	SelectSideChoice(side);
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::SelectSideChoice
*
* DESCRIPTION
*
* INPUTS
*     Side - 
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::SelectSideChoice(int side)
	{
	Check_Dlg_Button(IDC_TEAM_AUTO_CHECK, (PLAYERTYPE_RENEGADE == side));
	Check_Dlg_Button(IDC_TEAM_GDI_CHECK, (PLAYERTYPE_GDI == side));
	Check_Dlg_Button(IDC_TEAM_NOD_CHECK, (PLAYERTYPE_NOD == side));
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::GetSideChoice
*
* DESCRIPTION
*
* INPUTS
*     Side - 
*
* RESULT
*     NONE
*
******************************************************************************/

int DlgMPTeamSelect::GetSideChoice(void)
	{
	if (Is_Dlg_Button_Checked(IDC_TEAM_GDI_CHECK))
		{
		return PLAYERTYPE_GDI;
		}
	else if (Is_Dlg_Button_Checked(IDC_TEAM_NOD_CHECK))
		{
		return PLAYERTYPE_NOD;
		}

	return PLAYERTYPE_RENEGADE;
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::RequestWOLGameInfo
*
* DESCRIPTION
*     Send a request to the game server for informaiton about the game.
*
* INPUTS
*     NONE
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::RequestWOLGameInfo(void)
	{
	WWDEBUG_SAY(("DlgMPTeamSelect requesting game info\n"));

	// Get the hosts name and send a request for player information.
	const RefPtr<ChannelData>& channel = mWOLSession->GetCurrentChannel();

	if (channel.IsValid())
		{
		Observer<GameOptionsMessage>::NotifyMe(*mWOLSession);
		mWOLSession->SendPrivateGameOptions(channel->GetName(), "RGINFO");
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::ShowTimeRemaining
*
* DESCRIPTION
*     Set the time remaining text
*
* INPUTS
*     Seconds - Seconds remaining in the game
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::ShowTimeRemaining(float remainingSeconds)
	{
	int hours = 0;
	int mins = 0;
	int seconds = 0;

	cMiscUtil::Seconds_To_Hms(remainingSeconds, hours, mins, seconds);

	WideStringClass timeString(0, true);
	timeString.Format(L"%02d:%02d:%02d", hours, mins, seconds);
	
	WideStringClass text(0, true);
	text.Format(L"%s: %s", TRANSLATION(IDS_MP_TIME_REMAINING), (const WCHAR*)timeString);
	Set_Dlg_Item_Text(IDC_TIME_REMAINING_TEXT, (const WCHAR*)text);
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::FindPlayerInListCtrl
*
* DESCRIPTION
*     Find a player entry in the player (GDI or Nod) list control.
*
* INPUTS
*     Name  - Name of player to look for.
*     List  - On return; List control containing player entry.
*     Index - On return; Player entry list index
*
* RESULT
*     True if player found in one of the lists.
*
******************************************************************************/

bool DlgMPTeamSelect::FindPlayerInListCtrl(const WCHAR* name, ListCtrlClass*& outList, int& outIndex)
	{
	// Check in GDI player list
	ListCtrlClass* list = (ListCtrlClass*)Get_Dlg_Item(IDC_GDI_LIST_CTRL);

	if (list)
		{
		int index = list->Find_Entry(COL_NAME, name);

		if (index != -1)
			{
			outList = list;
			outIndex = index;
			return true;
			}
		}

	// Check in Nod player list
	list = (ListCtrlClass*)Get_Dlg_Item(IDC_NOD_LIST_CTRL);

	if (list)
		{
		int index = list->Find_Entry(COL_NAME, name);

		if (index != -1)
			{
			outList = list;
			outIndex = index;
			return true;
			}
		}

	return false;
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::HandleNotification(ChannelEvent)
*
* DESCRIPTION
*     Handle channel events that occur while the user is deceiding on the team.
*
* INPUTS
*     ChannelEvent - 
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::HandleNotification(ChannelEvent& event)
	{
	// This user has been kicked from the game.
	if (ChannelKicked == event.GetStatus())
		{
		DlgMsgBox::DoDialog(TRANSLATE(IDS_MENU_SERVER_MESSAGE_TITLE),
			TRANSLATE(IDS_MENU_SERVER_KICKED_MESSAGE));

		End_Dialog();
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::HandleNotification(UserEvent)
*
* DESCRIPTION
*     Handle user events that occur while the user is making their team choice.
*
* INPUTS
*
* RESULT
*
******************************************************************************/

void DlgMPTeamSelect::HandleNotification(UserEvent& userEvent)
	{
	const RefPtr<UserData>& user = userEvent.Subject();

	if (user.IsValid() == false)
		{
		return;
		}

	// Show clan information for users as it arrives
	switch (userEvent.GetEvent())
		{
#if(0) // Denzil 02/24/02 Day 1 patch - Removed clan until we fix formatting
		case UserEvent::SquadInfo:
			{
			ListCtrlClass* list = NULL;
			int itemIndex = -1;
			bool found = FindPlayerInListCtrl(user->GetName(), list, itemIndex);

			if (found)
				{
				RefPtr<SquadData> clan = user->GetSquad();

				if (clan.IsValid())
					{
					WideStringClass clanAbbr(0, true);
					clanAbbr = clan->GetAbbr();
					list->Set_Entry_Text(itemIndex, COL_CLAN, clanAbbr);
					}
				}
			}
			break;
#endif

#if(0)
		case UserEvent::Join:
			mWOLSession->RequestUserDetails(user, REQUEST_SQUADINFO);
			break;
#endif

		// Remove users that leave the game.
		case UserEvent::Leave:
			{
			ListCtrlClass* list = NULL;
			int itemIndex = -1;
			bool found = FindPlayerInListCtrl(user->GetName(), list, itemIndex);

			if (found)
				{
				list->Delete_Entry(itemIndex);
				}
			}
			break;

		default:
			break;
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::HandleNotification(GameOptionsMessage)
*
* DESCRIPTION
*     Handle game options messages that come in from the server.
*
* INPUTS
*     GameOpts - 
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::HandleNotification(GameOptionsMessage& message)
	{
	// Only listen to messages coming for the game host
	const RefPtr<ChannelData>& channel = mWOLSession->GetCurrentChannel();

	if (channel.IsValid() == false)
		{
		return;
		}

	const WideStringClass& hostName = channel->GetName();
	WideStringClass sender(0, true);
	sender = message.GetSendersName();

	if (hostName.Compare_No_Case(sender) == 0)
		{
		static struct {const char* Token; GameOptionsDispatchFunc Dispatch;} _dispatch[] =
			{
			{"GINFO:", ProcessWOLGameInfo},
			{"TINFO:", ProcessWOLTeamInfo},
			{"PINFO:", ProcessWOLPlayerInfo},
			{NULL, NULL}
			};

		int index = 0;
		const char* token = _dispatch[index].Token;
		const char* options = message.GetOptions();

		while (token)
			{
			// Find the first occurance of the token in the message
			char* cmd = strstr(options, token);

			// If the token was found and it is at the start of the message
			// then invoke the handler for this message.
			if (cmd && cmd == options)
				{
				const char* data = (options + strlen(token));
				_dispatch[index].Dispatch(*this, data);

				// We have heard from the host so it is okay to allow the player to start.
				Enable_Dlg_Item(IDC_STARTGAME, true);
				break;
				}

			++index;
			token = _dispatch[index].Token;
			}
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::ProcessWOLGameInfo
*
* DESCRIPTION
*     Process the game information options packet.
*
* INPUTS
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::ProcessWOLGameInfo(DlgMPTeamSelect& dialog, const char* data)
	{
	if (data)
		{
		char info[255];
		strncpy(info, data, 255);

		// Get players name
		unsigned long mapCRC = 0;
		PARSE_HEXDWORD(info, " ", mapCRC);

		StringClass mapname(64, true);
		ModPackageMgrClass::Find_Filename_From_CRC ("*.mix", mapCRC, &mapname);
		
		WideStringClass text(255, true);
		text.Format(TRANSLATE (IDS_MENU_MAP_NAME_FORMAT), (const char*)mapname);
		dialog.Set_Dlg_Item_Text(IDC_MAPNAME_TEXT, text);

		float timeRemaining = 0.0f;
		PARSE_FLOAT(NULL, " ", timeRemaining);
		dialog.mTimeRemaining = timeRemaining;
		dialog.ShowTimeRemaining(timeRemaining);

		int gdiScore = 0;
		PARSE_INT(NULL, " ", gdiScore);
		text.Format(TRANSLATE (IDS_MENU_SCORE_NAME_FORMAT), gdiScore);
		dialog.Set_Dlg_Item_Text(IDC_GDI_SCORE, text);

		int nodScore = 0;
		PARSE_INT(NULL, " ", nodScore);
		text.Format(TRANSLATE (IDS_MENU_SCORE_NAME_FORMAT), nodScore);
		dialog.Set_Dlg_Item_Text(IDC_NOD_SCORE, text);

		// Clear the player lists
		ListCtrlClass* list = (ListCtrlClass*)dialog.Get_Dlg_Item(IDC_GDI_LIST_CTRL);

		if (list)
			{
			list->Delete_All_Entries();
			}

		list = (ListCtrlClass*)dialog.Get_Dlg_Item(IDC_NOD_LIST_CTRL);

		if (list)
			{
			list->Delete_All_Entries();
			}
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::ProcessWOLTeamInfo
*
* DESCRIPTION
*     Process the team information options packet.
*
* INPUTS
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::ProcessWOLTeamInfo(DlgMPTeamSelect& dialog, const char* data)
	{
	if (data)
		{
		char info[255];
		strncpy(info, data, 255);

		// Get team GDI information
		int teamID = 0;
		PARSE_INT(info, " ", teamID);

		int score = 0;
		PARSE_INT(NULL, " ", score);

		// Output info
		WideStringClass text(0, true);
		text.Format(TRANSLATE (IDS_MENU_SCORE_NAME_FORMAT), score);

		int ctrlID = ((teamID == PLAYERTYPE_GDI) ? IDC_GDI_SCORE : IDC_NOD_SCORE);
		dialog.Set_Dlg_Item_Text(ctrlID, text);
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::ProcessWOLPlayerInfo
*
* DESCRIPTION
*     Process the per player information packet.
*
* INPUTS
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::ProcessWOLPlayerInfo(DlgMPTeamSelect& dialog, const char* data)
	{
	if (data)
		{
		char info[255];
		strncpy(info, data, 255);

		// Get players name
		char* name = "";
		PARSE_STRING(info, " ", name);

		// Team type
		int type = -1;
		PARSE_INT(NULL, " ", type);

		// Rank
		int rung = 0;
		PARSE_INT(NULL, " ", rung);

		// Kills
		int kills = 0;
		PARSE_INT(NULL, " ", kills);

		// Deaths
		int deaths = 0;
		PARSE_INT(NULL, " ", deaths);

		// Score
		int score = 0;
		PARSE_INT(NULL, " ", score);

		int listID = ((type == PLAYERTYPE_GDI) ? IDC_GDI_LIST_CTRL : IDC_NOD_LIST_CTRL);
		ListCtrlClass* list = (ListCtrlClass*)dialog.Get_Dlg_Item(listID);

		if (list)
			{
			WideStringClass playerName(64, true);
			playerName = name;

			int itemIndex = list->Find_Entry(COL_NAME, playerName);
			
			if (itemIndex == -1)
				{
				itemIndex = list->Insert_Entry(list->Get_Entry_Count(), L"");
				}

			if (itemIndex != -1)
				{
				WideStringClass text(255, true);

				// Set the players name and clan affiliation
				list->Set_Entry_Text(itemIndex, COL_NAME, playerName);

#if(0) // Denzil 02/24/02 Day 1 patch - Remove clan until we can fix formating
				RefPtr<UserData> user = dialog.mWOLSession->FindUser(playerName);

				if (user.IsValid())
					{
					RefPtr<SquadData> clan = user->GetSquad();

					if (clan.IsValid())
						{
						text = clan->GetAbbr();
						list->Set_Entry_Text(itemIndex, COL_CLAN, text);
						}
					}
#endif
				
				text.Format(L"%d/%d", kills, deaths);
				list->Set_Entry_Text(itemIndex, COL_KD, text);

				list->Set_Entry_Int(itemIndex, COL_RANK, rung);
				list->Set_Entry_Int(itemIndex, COL_SCORE, score);

				list->Sort(ListSortCallback, 0);
				}
			}
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::HandleNotification(PlayerMgrEvent)
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
*
******************************************************************************/

void DlgMPTeamSelect::HandleNotification(PlayerMgrEvent& event)
	{
	PLAYERMGR_ACTION action = event.GetAction();

	if ((action == PLAYER_ACTIVATED))// || (action == PLAYER_ADDED))
		{
		AddLANPlayerInfo(event.Subject());
		}
	else if ((action == PLAYER_DEACTIVATED) || (action == PLAYER_REMOVED))
		{
		RemoveLANPlayerInfo(event.Subject());
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::ProcessWithLANPlayers
*
* DESCRIPTION
*
* INPUTS
*     NONE
*
* RESULT
*     NONE
*
******************************************************************************/

void DlgMPTeamSelect::PopulateWithLANPlayers(void)
	{
	SList<cPlayer>* playerList = cPlayerManager::Get_Player_Object_List();
	SLNode<cPlayer>* playerNode = playerList->Head();

	while (playerNode)
		{
		cPlayer* player = playerNode->Data();

		if (player->Get_Is_Active().Is_True())
			{
			AddLANPlayerInfo(player);
			}

		playerNode = playerNode->Next();
		}
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::AddLANPlayerInfo
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
*
******************************************************************************/

void DlgMPTeamSelect::AddLANPlayerInfo(cPlayer* player)
	{
	WWASSERT(player != NULL);
	RemoveLANPlayerInfo(player);
	
	int playerType = player->Get_Player_Type();
	int listID = ((playerType == PLAYERTYPE_GDI) ? IDC_GDI_LIST_CTRL : IDC_NOD_LIST_CTRL);

	ListCtrlClass* list = (ListCtrlClass*)Get_Dlg_Item(listID);
	WWASSERT(list != NULL);

	int itemIndex = list->Insert_Entry(list->Get_Entry_Count(), L"");

	if (itemIndex >= 0)
		{
		list->Set_Entry_Text(itemIndex, COL_NAME, player->Get_Name());
		list->Set_Entry_Int(itemIndex, COL_RANK, player->Get_Rung());
		list->Set_Entry_Int(itemIndex, COL_SCORE, player->Get_Score());

		WideStringClass text(0, true);
		text.Format(L"%d/%d", player->Get_Kills(), player->Get_Deaths());
		list->Set_Entry_Text(itemIndex, COL_KD, text);

		// If this is the player client the mark there name with a star
		const WideStringClass& nickname = cNetInterface::Get_Nickname();

		if (nickname.Compare_No_Case(player->Get_Name()) == 0)
			{
			list->Add_Icon(itemIndex, COL_NAME, "IF_LRGSTAR.TGA");
			list->Set_Entry_Color(itemIndex, COL_RANK, Vector3(1.0F, 1.0F, 1.0F));
			list->Set_Entry_Color(itemIndex, COL_NAME, Vector3(1.0F, 1.0F, 1.0F));
			list->Set_Entry_Color(itemIndex, COL_KD, Vector3(1.0F, 1.0F, 1.0F));
			list->Set_Entry_Color(itemIndex, COL_SCORE, Vector3(1.0F, 1.0F, 1.0F));

			SelectSideChoice(playerType);
			}
		}

	list->Sort(ListSortCallback, 0);
	}


/******************************************************************************
*
* NAME
*     DlgMPTeamSelect::RemoveLANPlayerInfo
*
* DESCRIPTION
*
* INPUTS
*
* RESULT
*
******************************************************************************/

void DlgMPTeamSelect::RemoveLANPlayerInfo(cPlayer* player)
	{
	WWASSERT(player != NULL);

	ListCtrlClass* list = NULL;
	int itemIndex = -1;
	bool found = FindPlayerInListCtrl(player->Get_Name(), list, itemIndex);

	if (found)
		{
		list->Delete_Entry(itemIndex);
		}
	}
