//Aaron Horne -- 3/26/02 -- MERCS


#include "MW4Headers.hpp"
#include "MWNewsManager.hpp"
#include "MWGame.hpp"
//#include "MWApplication.hpp"
//#include "MWTable.hpp"
//#include "Salvage.hpp"
//#include "Mech.hpp"
//#include "SubsystemClassData.hpp"
//#include "Weapon.hpp"
#include "MWCampaign.hpp"
#include "MWCorporation.hpp"

#include <Stuff\Stuff.hpp> //for the MString

#include "..\Content\Mercenaries\scriptstrings.h"

//#include <Adept\Tool.hpp>

//############################################################################
//####################     MWNewsPlug   ######################################
//############################################################################

MWNewsPlug::MWNewsPlug(Stuff::MemoryStream *stream) : Plug(Plug::DefaultData)
{
	*stream >> m_audioClip;
	*stream >> m_title;
	*stream >> m_stringID;
	*stream >> m_availableFlag;
	*stream >> m_revealOnCycle;

	m_availableFlag = 1; //TEST
	int i;
	for (i=0; i<MWNEWSMANAGER_MAX_NUMBER_OF_MISSIONS_TO_REVEAL_ON; i++)
	{
		*stream >> m_revealOnMission[i];
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWNewsPlug::~MWNewsPlug()
{
	//empty
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//void MWNewsPlug::WriteToText(Stuff::NotationFile& file)
//{
	//not sure why this is here -- i got it from lancemate.cpp -- I don't think I want to use it so I won't for now
//	Check_Object(this);
//	Check_Object(&file);

//	Stuff::Page *page = file.AddPage (m_lancemateName);
//	page->AppendEntry ("StoryStringID",m_lancemateName);
//	Resource model_resource(m_lanceDataListID);
//	Verify(model_resource.DoesResourceExist());
//	page->AppendEntry("AudioClip",m_TalkerSuffix);
//	page->AppendEntry ("RevealOnCycle", model_resource.GetName());
//	page->AppendEntry("RevealOn1Mission",m_MustSurvive);
//}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MWNewsPlug::Save(MemoryStream *stream)
{
	*stream << m_audioClip;
	*stream << m_title;
	*stream << m_stringID;
	*stream << m_availableFlag;
	*stream << m_revealOnCycle;

	int i;
	for (i=0; i<MWNEWSMANAGER_MAX_NUMBER_OF_MISSIONS_TO_REVEAL_ON; i++)
	{
		*stream << m_revealOnMission[i];
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MWNewsPlug::ConstructStream(MemoryStream *stream,Stuff::Page *page)
{
	Check_Object (stream);
	Check_Object (page);

	MString audioString;
	const char *audioName;
	page->GetEntry("AudioClip", &audioName, true);
	audioString = audioName;
	*stream << audioString;

	MString titleString;
	const char *titleName;
	page->GetEntry("Title", &titleName, true);
	titleString = titleName;
	*stream << titleString;

	int stringIndex;
	page->GetEntry("StoryStringID", &stringIndex, true);
	*stream << stringIndex;

	int availableFlag = 0; //initially not available
	*stream << availableFlag;

	int revealOnCycle;
	if (page->GetEntry("RevealOnCycle", &revealOnCycle) == false)
	{
		revealOnCycle = 1000; //high default value if nothing was entered in the file
	}
	*stream << revealOnCycle;

	char *buffer = new char[18]; //18 allows for 3 additional chars in RevealOnXXXMission
	int stringID;
	int i;
	for (i=0; i<MWNEWSMANAGER_MAX_NUMBER_OF_MISSIONS_TO_REVEAL_ON; i++)
	{
		sprintf (buffer, "RevealOn%dMission", i);
		if (page->GetEntry(buffer, &stringID) == false)
		{
			stringID = -1; //-1 signifies that it is not being used -- was not entered in the file
		}
		*stream << stringID;
	}
	delete buffer;
}

//###################################################################################
//###########################    MWNewsManager    ###################################
//###################################################################################

//Stuff
MWNewsManager::ClassData*
	MWNewsManager::DefaultData = NULL;

MWNewsManager *MWNewsManager::Instance = NULL;//necessary?
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MWNewsManager::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			MWNewsManagerID,
			"MechWarrior4::MWNewsManager",
			Receiver::DefaultData,
			0,
			NULL
		);
	Check_Object(DefaultData);
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MWNewsManager::TerminateClass()
{
	Check_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWNewsManager::MWNewsManager(MemoryStream *stream)
	: Receiver(DefaultData),
  	m_newsChain(NULL)
{
	Check_Pointer(stream);
	int number,i;

	*stream >> number;
	for (i = 0;i<number;i++)
	{
		MWNewsPlug *newsPlug;

		newsPlug = new MWNewsPlug (stream);
		Check_Object(newsPlug);
		m_newsChain.Add(newsPlug);
	}
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWNewsManager::~MWNewsManager()
{
	Check_Object(this);
	m_newsChain.DeletePlugs();
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWNewsManager* MWNewsManager::MakeNewMWNewsManager(const char *newsmanager_name)
{
	Check_Pointer(newsmanager_name);

	Resource newsmanager_resource(newsmanager_name);
	Verify(newsmanager_resource.DoesResourceExist());
	newsmanager_resource.LoadData();

	MWNewsManager *new_newsmanager;
	new_newsmanager = new MWNewsManager(&newsmanager_resource);
	Check_Object(new_newsmanager);

	return new_newsmanager;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// -- a not needed part of the global pointer thing in InitIA in MW4Shell.cpp -- left here for posterity and future fixing
/*
MWNewsManager *MWNewsManager::MakeNewMWNewsManager(const ResourceID& newsmanager_resource_id)
{
	MWNewsManager *new_newsmanager;
	if(newsmanager_resource_id != ResourceID::Null)
	{
		Resource newsmanager_resource(newsmanager_resource_id);
		Verify(newsmanager_resource.DoesResourceExist());
		newsmanager_resource.LoadData();
		
		new_newsmanager = new MWNewsManager(&newsmanager_resource);
		Check_Object(new_newsmanager);
	}
	else
		new_newsmanager = new MWNewsManager(NULL);

	return new_newsmanager;
}
*/

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

MWNewsManager* MWNewsManager::MakeNewMWNewsManager(Adept::ResourceID newsmanager_id)
{
	Resource newsmanager_resource(newsmanager_id);
	Verify(newsmanager_resource.DoesResourceExist());

	MWNewsManager *new_newsmanager;
	new_newsmanager = new MWNewsManager(&newsmanager_resource);
	Check_Object(new_newsmanager);

	return new_newsmanager;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MWNewsManager::ConstructNewsManagerStream(MemoryStream *stream,NotationFile *notation_file)
{
	Check_Pointer(stream);
	Check_Object (notation_file);

	NotationFile::PageIterator *pages = notation_file->MakePageIterator();
	Check_Object(pages);

	*stream << pages->GetSize ();
	Page *page_entry;
	while ((page_entry = pages->ReadAndNext()) != NULL)
	{
		Check_Object(page_entry);
		MWNewsPlug::ConstructStream (stream,page_entry);
	}
	delete pages;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MWNewsManager::Save(MemoryStream *stream)
{
	ChainIteratorOf<MWNewsPlug *> iterator(&m_newsChain);
	MWNewsPlug *news_plug;
	*stream << m_newsChain.GetSize();
	while((news_plug = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(news_plug);
		news_plug->Save (stream);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MWNewsManager::TestInstance() const
{
	Verify(IsDerivedFrom(DefaultData));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MWNewsManager::UpdateForNewCycle(void)
{
	int i;
	int missionID;
	int cycle;

	Check_Object (MWGame::GetInstance());

	CampaignMissionPlug *mission_plug;

	//loop through all the news plugs and see which need to be made active, and do so -- compare with completed missions
	ChainIteratorOf<MWNewsPlug *> iterator(&m_newsChain);
	MWNewsPlug *news_plug;
	while((news_plug = iterator.ReadAndNext()) != NULL)
	{
		Check_Object(news_plug);
		if (news_plug->GetAvailableFlag()) //if its already available... we dont need to check it
		{
			continue;
		}

		//check for cycle made available
		cycle = news_plug->GetRevealOnCycle();
		if (cycle <= MWGame::GetInstance()->m_CorporateStructure->GetCurrentCycle()) // == would be fine but <= just to make sure
		{
			news_plug->SetAvailableFlag(1); //1 = TRUE
			continue; //no need to check further...  the cycle check overrides mission availability
		}

		//These are OR'd 

		//check for reveal on completed missions
		for (i=0; i<MWNEWSMANAGER_MAX_NUMBER_OF_MISSIONS_TO_REVEAL_ON; i++)
		{
			missionID = news_plug->GetRevealOnMission(i);
			if (missionID < 0)
			{
				break; //if we get to an index set to less than 0, then we want to stop checking because no further missions were specified
			}
			mission_plug = MWGame::GetInstance()->m_campaign->FindMission(missionID);
			if (mission_plug->m_status != MWCampaign::Completed)
			{
				news_plug->SetAvailableFlag(0); //0 = FALSE
				break; //if we get to one that is not completed, no need to check for others
			}
			news_plug->SetAvailableFlag(1); //1 = TRUE
		}

		//designer forced is done with ABL... it just bypasses the whole thing and sets it to available
	}
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWNewsPlug *MWNewsManager::FindNews (MString news_title,bool case_sensitive)
{
	//
	// We can't use sorted chain or the data doesn't appear in the same order as the
	// campaign source file. But the normal chain does not have a find value.
	//
	Verify(news_title);
    
	ChainIteratorOf<MWNewsPlug *> find_iterator(&m_newsChain);
	MWNewsPlug *cur_news;
	while ((cur_news = find_iterator.ReadAndNext()) != NULL)
	{
		if (case_sensitive)
		{
			if (cur_news->GetTitle() == news_title)
				break;
		}
		else
		{
			if (!strnicmp ((char *) cur_news->GetTitle(),news_title,sizeof (news_title)))
				break;
		}
	}
	return cur_news;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MWNewsPlug *MWNewsManager::FindNews (int display_index)
{
	ChainIteratorOf<MWNewsPlug *> find_iterator(&m_newsChain);
	MWNewsPlug *cur_news;
	while ((cur_news = find_iterator.ReadAndNext()) != NULL)
	{
	if (cur_news->GetStringIndex() == display_index)
	  break;
	}
	return cur_news;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void MWNewsManager::GetAvailableNews (int **data, int &size) //create an array of scriptstring indices for available news
{
	size = 0;
	ChainIteratorOf<MWNewsPlug *> find_iterator(&m_newsChain);
	MWNewsPlug *cur_news;

	while ((cur_news = find_iterator.ReadAndNext()) != NULL) // Get the size
	{
		if (cur_news->GetAvailableFlag())
		{
			size++;
		}
	}

//	if (size)
//		*data = new int[size]; //GosMalloc/GosFree
//	else
//		return;

	int i=0;
	cur_news = find_iterator.GetNth(0); //rewind
	while ((cur_news = find_iterator.ReadAndNext()) != NULL)
	{
		if (cur_news->GetAvailableFlag())
		{
			(*data)[i] = cur_news->GetStringIndex();
			i++;
		}
	}

	return;
}
