#include "munga.h"
#pragma hdrstop

#include "mission.h"
#include "namelist.h"
#include "notation.h"
#include "graph2d.h"

//#############################################################################
//#######################    MissionHostData    ###############################
//#############################################################################

MissionHostData::MissionHostData(
	const CString &address_string,
	HostType host_type
):
	addressString(address_string),
	hostType(host_type)
{
}

MissionHostData::~MissionHostData()
{
}

//#############################################################################
//###########################    Mission    ###################################
//#############################################################################

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Mission::LoadOrdinalBitmaps(NotationFile *notation_file)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Load ordinal bitmaps from egg
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
	Check(notation_file);
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Make an entrylist of all the bitmap names
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	NameList *ord_namelist = notation_file->MakeEntryList("ordinals", "bitmap");
	if (!ord_namelist)
	{
   	Warn("No Ordinal Bitmaps in Egg \n");
		return;
	}
	Register_Object(ord_namelist);
	NameList::Entry *ord_entry = ord_namelist->GetFirstEntry();
	BitMap *new_bitmap;
	int index(0);
	while(ord_entry)
	{
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~
		// Get the bitmap pageName
		//~~~~~~~~~~~~~~~~~~~~~~~~
		//
		++index;
		CString ord_bitmap_name = ord_entry->GetChar();
		new_bitmap = new BitMap(notation_file, ord_bitmap_name);

		Register_Object(new_bitmap);
		ordinalBitmapChain.AddValue(new_bitmap, index);
		//
		//~~~~~~~~~~~~~~~~~~~~
		// Increment the index
		//~~~~~~~~~~~~~~~~~~~~
		//
		ord_entry = ord_entry->GetNextEntry();
	}

	Unregister_Object(ord_namelist);
	delete ord_namelist;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Mission::LoadTeamBitmaps(NotationFile *notation_file)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Load team bitmaps from egg
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
	Check(notation_file);
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Make an entrylist of all the team names
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	NameList *team_namelist = notation_file->MakeEntryList("teams", "team");
	if (!team_namelist)
	{
		return;
	}
	Register_Object(team_namelist);
	NameList::Entry *team_entry = team_namelist->GetFirstEntry();
	BitMap *new_bitmap;
	int index(0);
	while(team_entry)
	{
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~
		// Get the team pageName
		//~~~~~~~~~~~~~~~~~~~~~~~~
		//
		CString team_name = team_entry->GetChar();
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Get the Team Bitmap Page Name
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		const char *team_bitmap_name;
		notation_file->GetEntry(
			team_name,
			"bitmap",
			&team_bitmap_name
		);
		//
		//~~~~~~~~~~~~~~~~~~
		// Create the bitMap
		//~~~~~~~~~~~~~~~~~~
		//
		new_bitmap = new BitMap(notation_file, team_bitmap_name);
		Register_Object(new_bitmap);
		teamBitmapChain.AddValue(new_bitmap, index);
		//
		//~~~~~~~~~~~~~~~~~~~~
		// Increment the index
		//~~~~~~~~~~~~~~~~~~~~
		//
      ++index;
		team_entry = team_entry->GetNextEntry();
	}
	Unregister_Object(team_namelist);
	delete team_namelist;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Mission::LoadNameBitmaps(NotationFile *notation_file)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Load name bitmaps from egg
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
	Check(notation_file);
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Make an entrylist of all the large bitmap names
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	NameList *large_namelist = notation_file->MakeEntryList("largebitmap", "bitmap");
	if (!large_namelist)
	{
		Warn("No Large NameBitmaps in Egg \n");
		return;
	}
	Register_Object(large_namelist);
	NameList::Entry *large_entry = large_namelist->GetFirstEntry();

	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Make an entrylist of all the small bitmap names
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	NameList *small_namelist = notation_file->MakeEntryList("smallbitmap", "bitmap");
	if (!small_namelist)
	{
		Warn("No Small NameBitmaps in Egg \n");
		return;
	}
	Register_Object(small_namelist);
	NameList::Entry *small_entry = small_namelist->GetFirstEntry();

	BitMap *new_bitmap;
	CString large_bitmap_name, small_bitmap_name;
	int index(0);
	while(large_entry && small_entry)
	{
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Create the large Name bitmap
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		++index;
		large_bitmap_name = large_entry->GetChar();
		new_bitmap = new BitMap(notation_file, large_bitmap_name);
		Register_Object(new_bitmap);
		largeNameBitmapChain.AddValue(new_bitmap, index);
      //
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Create the small Name bitmap
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		small_bitmap_name = small_entry->GetChar();
		new_bitmap = new BitMap(notation_file, small_bitmap_name);
		Register_Object(new_bitmap);
		smallNameBitmapChain.AddValue(new_bitmap, index);

		small_entry = small_entry->GetNextEntry();
		large_entry = large_entry->GetNextEntry();
	}

	Unregister_Object(large_namelist);
	delete large_namelist;

	Unregister_Object(small_namelist);
	delete small_namelist;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Mission::LoadLandmarkBitmaps(NotationFile *notation_file)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Load Landmark bitmaps from egg
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
	Check(notation_file);
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Make an entrylist of all the landmark names
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	NameList *landmark_namelist = notation_file->MakeEntryList("landmarks", "landmark");
	if (!landmark_namelist)
	{
		return;
	}
	Register_Object(landmark_namelist);
	NameList::Entry *landmark_entry = landmark_namelist->GetFirstEntry();
	BitMap *new_bitmap;
	int index(0);
	while(landmark_entry)
	{
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~
		// Get the landmark pageName
		//~~~~~~~~~~~~~~~~~~~~~~~~
		//
		CString landmark_name = landmark_entry->GetChar();
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Get the landmark Bitmap Page Name
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		const char *landmark_bitmap_name;
		notation_file->GetEntry(
			landmark_name,
			"bitmap",
			&landmark_bitmap_name
		);
		//
		//~~~~~~~~~~~~~~~~~~
		// Create the bitMap
		//~~~~~~~~~~~~~~~~~~
		//
		new_bitmap = new BitMap(notation_file, landmark_bitmap_name);
		Register_Object(new_bitmap);
		landmarkBitmapChain.AddValue(new_bitmap, index);
		//
		//~~~~~~~~~~~~~~~~~~~~
		// Increment the index
		//~~~~~~~~~~~~~~~~~~~~
		//
		++index;
		landmark_entry = landmark_entry->GetNextEntry();
	}
	Unregister_Object(landmark_namelist);
	delete landmark_namelist;
}


//
//#############################################################################
//#############################################################################
//
Mission::Mission(
	NotationFile *notation_file,
	ResourceFile *resources
):
	missionHostSocket(NULL),
	largeNameBitmapChain(NULL, True),
	smallNameBitmapChain(NULL, True),
	ordinalBitmapChain(NULL, True),
	teamBitmapChain(NULL, True),
	landmarkBitmapChain(NULL, True),
	scenarioRoleChain(NULL, True)
{
	Check(notation_file);
	Check(resources);
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// NULL out All allocated variables
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	colorName = NULL;
	badgeName = NULL;
	dropZoneName = NULL;
	gameModel = NULL;
	missionTime = NULL;
	missionWeather = NULL;
	scenarioName = NULL;
	positionName = NULL;
	//
	//-----------------
	// Get the map name
	//-----------------
	//
	Logical ret;
	const char *map_name;

	ret = notation_file->GetEntry("mission", "map", &map_name);
	if (!ret)
	{
		DEBUG_STREAM << "ERROR: no map in egg!\n" << std::flush;
		PostQuitMessage(AbortExitCodeID);
	}

	//
	//-----------------------
	// Get the mission length
	//-----------------------
	//
	gameLength = 0.0;
	notation_file->GetEntry("mission", "length", &gameLength);

	//
	//------------------------
	// Get the map resource id
	//------------------------
	//
	ResourceDescription *map =
		resources->FindResourceDescription(
			map_name,
			ResourceDescription::MakeMessageStreamResourceType
		);
	if (!map)
	{
		DEBUG_STREAM << "ERROR: Couldn't find map in resource file!\n" << std::flush;
		PostQuitMessage(AbortExitCodeID);
	}
	Check(map);
	mapID = map->resourceID;

	//
	//----------------------------------
	// Get the existance map resource id
	//----------------------------------
	//
	map =
		resources->FindResourceDescription(
			map_name,
			ResourceDescription::ExistanceBoxStreamResourceType
		);
	if (!map)
	{
		DEBUG_STREAM << "ERROR: Couldn't find existance map in resource file!\n" << std::flush;
		PostQuitMessage(AbortExitCodeID);
	}
	Check(map);
	existanceMapID = map->resourceID;

	//
	//---------------------------------------------
	// Get the mission time, weather, and scenario
	//--------------------------------------------
	//
	const char *mission_time;
	const char *mission_weather;
	const char *mission_scenario;

	ret = notation_file->GetEntry("mission", "time", &mission_time);
	if (!ret)
	{
		DEBUG_STREAM << "ERROR: no time in egg!\n" << std::flush;
		PostQuitMessage(AbortExitCodeID);
	}

	ret = notation_file->GetEntry("mission", "weather", &mission_weather);
	if (!ret)
	{
		DEBUG_STREAM << "ERROR: no weather in egg!\n" << std::flush;
		PostQuitMessage(AbortExitCodeID);
	}

	ret = notation_file->GetEntry("mission", "scenario", &mission_scenario);
	if (!ret)
	{
		DEBUG_STREAM << "ERROR: no scenario in egg!\n" << std::flush;
		PostQuitMessage(AbortExitCodeID);
	}

	int length;

	length = strlen(mission_time) + 1;
	missionTime = new char[length];
	Register_Pointer(missionTime);			// safer to register BEFORE using
	Str_Copy(missionTime, mission_time, length);

	length = strlen(mission_weather) + 1;
	missionWeather = new char[length];
	Register_Pointer(missionWeather);		// safer to register BEFORE using
	Str_Copy(missionWeather, mission_weather, length);

	length = strlen(mission_scenario) + 1;
	scenarioName = new char[length];
	Register_Pointer(scenarioName);		// safer to register BEFORE using
	Str_Copy(scenarioName, mission_scenario, length);

	//
	//--------------------------
	// Get the mission host data
	//--------------------------
	//
	NameList *entry_list;
	NameList::Entry *entry;

	playerCount = 0;
	entry_list = notation_file->MakeEntryList("pilots", "pilot");
	Register_Object(entry_list);
	entry = entry_list->GetFirstEntry();
	while (entry != NULL)
	{
		Check(entry);

		//
		// Get the host address character string
      //
		char *host_address_pointer = entry->GetChar();
		Check_Pointer(host_address_pointer);

		//
		// Create the host address string
		//
		CString host_address_string(host_address_pointer);
		Check(&host_address_string);

		//
		// Get the host type
		//
		int host_type;

		ret = notation_file->GetEntry(
			host_address_pointer,
			"hostType",
			&host_type
		);
		if (!ret)
		{
			DEBUG_STREAM << "ERROR: no host type in egg!\n" << std::flush;
			PostQuitMessage(AbortExitCodeID);
		}

		//
		// Create the mission host data
		//
		MissionHostData *mission_host_data;

		mission_host_data =
			new MissionHostData(
				host_address_string,
				(HostType)host_type
			);
		Register_Object(mission_host_data);

		//
		// Add to the host socket
      //
		missionHostSocket.Add(mission_host_data);
		++playerCount;

		entry = entry->GetNextEntry();
	}
	#if DEBUG_LEVEL>0
		SChainIteratorOf<MissionHostData*> iterator(&missionHostSocket);
		Check(&iterator);
		Verify(iterator.GetSize() > 0);
	#endif
	Unregister_Object(entry_list);
	delete entry_list;

	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Load all the Bitmaps from the Notation File
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	LoadOrdinalBitmaps(notation_file);
	LoadNameBitmaps(notation_file);
	//LoadTeamBitmaps(notation_file);
   //LoadLandmarkBitmaps(notation_file);

	positionName = NULL;
}

//
//#############################################################################
//#############################################################################
//
Mission::~Mission()
{
	Check(this);

	//
	// Delete mission host data
	//
	SChainIteratorOf<MissionHostData*> iterator(&missionHostSocket);
	Check(&iterator);
	iterator.DeletePlugs();

	//
	// Delete the text fields
	//
	if (gameModel)
	{
		Unregister_Pointer(gameModel);
		delete[] gameModel;
	}
	if (dropZoneName)
	{
		Unregister_Pointer(dropZoneName);
		delete[] dropZoneName;
	}
	if (colorName)
	{
		Unregister_Pointer(colorName);
		delete[] colorName;
	}
	if (badgeName)
	{
		Unregister_Pointer(badgeName);
		delete[] badgeName;
	}
	if (positionName)
	{
		Unregister_Pointer(positionName);
		delete[] positionName;
	}
	if (missionTime)
	{
		Unregister_Pointer(missionTime);
		delete[] missionTime;
	}
	if (missionWeather)
	{
		Unregister_Pointer(missionWeather);
		delete[] missionWeather;
	}
	if (scenarioName)
	{
		Unregister_Pointer(scenarioName);
		delete[] scenarioName;
	}
	//
	//~~~~~~~~~~~~~~~~~~~~~~~
	// delete all the bitmaps
	//~~~~~~~~~~~~~~~~~~~~~~~
	//
	VChainIteratorOf<BitMap*,int> small_iterator(smallNameBitmapChain);
	small_iterator.DeletePlugs();

	VChainIteratorOf<BitMap*,int> large_iterator(largeNameBitmapChain);
	large_iterator.DeletePlugs();

	VChainIteratorOf<BitMap*,int> ordinal_iterator(ordinalBitmapChain);
	ordinal_iterator.DeletePlugs();

	VChainIteratorOf<BitMap*,int> team_iterator(teamBitmapChain);
	team_iterator.DeletePlugs();

	VChainIteratorOf<BitMap*,int> landmark_iterator(landmarkBitmapChain);
	landmark_iterator.DeletePlugs();


	VChainIteratorOf<ScenarioRole*, CString> role_iterator(scenarioRoleChain);
	role_iterator.DeletePlugs();
}

//
//#############################################################################
//#############################################################################
//
void
	Mission::SetPlayerData(
		NotationFile * //notation_file
	)
{
}

//
//#############################################################################
//#############################################################################
//
Logical
	Mission::TestInstance() const
{
	Check(&missionHostSocket);
	return True;
}

//#############################################################################
//######################    Mission_HostIterator    ###########################
//#############################################################################

Mission_HostIterator::Mission_HostIterator(Mission *mission):
	SChainIteratorOf<MissionHostData*>(&mission->missionHostSocket)
{
}

Mission_HostIterator::~Mission_HostIterator()
{
}
