
#include "MW4Headers.hpp"

#include "AI_Specials.hpp"
#include "aiutils.hpp"
#include <Adept\Resource.hpp>
#include "MWPlayer.hpp"
#include "VehicleInterface.hpp"
#include <gosfx\gosfx.hpp>
#include <Adept\Effect.hpp>
#include <Adept\Map.hpp>



using namespace MW4AI;

const Stuff::Scalar max_delay_between_fireworks = 2.5f;
const Stuff::Scalar max_fireworks_origin_skew = 40.0f;


Specials* Specials::m_Instance = 0;

Specials::Specials()
	: m_RefCount(0)
	, m_Resource("ai\\ai.specials")
	, m_FireworksStopTime(0)
	, m_NextFireworkStartTime(0)
	, m_LaunchConfetti(false)
	, m_ConfettiLaunched(false)
{
/*
	Verify(m_Resource.DoesResourceExist());

	m_Resource.Rewind();
	m_NotationFile.Assimilate(new Stuff::NotationFile(&m_Resource));

	m_FlareResource.Assimilate(new Adept::Resource(GetResourceName("Signal Flare","signal_flare").c_str()));
	m_ConfettiResource.Assimilate(new Adept::Resource(GetResourceName("confetti","confetti").c_str()));

	{
		std::vector<std::string> resource_names;
		GetResourceName_Multiple("Fireworks","firework",resource_names);

		{for (std::vector<std::string>::const_iterator i = resource_names.begin();
			  i != resource_names.end();
			  ++i)
		{
			Stuff::Auto_Ptr<Adept::Resource> temp(new Adept::Resource((*i).c_str()));
			m_FireworksResource.push_back(temp);
		}}
	}

	{
		std::vector<std::string> resource_names;
		GetResourceName_Multiple("Fighter Smoke","smoke",resource_names);

		{for (std::vector<std::string>::const_iterator i = resource_names.begin();
			  i != resource_names.end();
			  ++i)
		{
			Stuff::Auto_Ptr<Adept::Resource> temp(new Adept::Resource((*i).c_str()));
			m_FighterSmoke.push_back(temp);
		}}
	}
*/
}

Specials::~Specials()
{
}

void Specials::IncrementRefCount()
{
	if (m_Instance == 0)
	{
		m_Instance = new MW4AI::Specials();
	}

	++m_Instance->m_RefCount;
}

void Specials::DecrementRefCount()
{
	Verify(m_Instance != 0);
	Verify(m_Instance->m_RefCount > 0);

	--(m_Instance->m_RefCount);

	if (m_Instance->m_RefCount == 0)
	{
		delete m_Instance;
		m_Instance = 0;
	}
}

Specials* Specials::Instance()
{
	return (m_Instance);
}

std::string Specials::GetResourceName(const std::string& block_name, const std::string& item_name)
{
	Verify(m_NotationFile.GetPointer() != 0);

	Stuff::Page* page = m_NotationFile->FindPage(block_name.c_str());

	if (page == 0)
	{
		Verify(!"Item not found.  Make sure you have the latest CONTENT\\AI\\AI.SPECIALS file.");
		return ("");
	}

	Stuff::Note* note = page->FindNote(item_name.c_str());

	if (note == 0)
	{
		Verify(!"Item not found.");
		return ("");
	}

	const char* rv;
	note->GetEntry(&rv);
	return (rv);
}

void Specials::GetResourceName_Multiple(const std::string& block_name, const std::string& item_name, std::vector<std::string>& resource_names)
{
	Verify(m_NotationFile.GetPointer() != 0);

	Stuff::Page* page = m_NotationFile->FindPage(block_name.c_str());

	if (page == 0)
	{
		Verify(!"Item not found.  Make sure you have the latest CONTENT\\AI\\AI.SPECIALS file.");
		return;
	}

	Stuff::Note* note_total = page->FindNote("total");
	if (note_total == 0)
	{
		return;
	}

	int total;
	note_total->GetEntry(&total);
	Verify(total >= 0);

	{for (int i = 0;
		  i < total;
		  ++i)
	{
		std::string modified_item_name(item_name);
		modified_item_name += IntToString(i);

		Stuff::Note* note = page->FindNote(modified_item_name.c_str());

		if (note == 0)
		{
			Verify(!"Item not found.");
		}
		else
		{
			const char* resource_name;
			note->GetEntry(&resource_name);
			resource_names.push_back(resource_name);
		}
	}}
}

MWObject* Specials::GetPlayerVehicle()
{
	if (Adept::Player::GetInstance() == 0)
	{
		return (0);
	}

	MechWarrior4::MWPlayer* p = Cast_Object(MechWarrior4::MWPlayer*,Adept::Player::GetInstance());
	if ((p == 0) ||
		(p->GetInterface() == 0))
	{
		return (0);
	}

	return (p->GetInterface()->vehicle);
}

int Specials::GetNumFireworkTypes() const
{
	return (m_FireworksResource.size());
}

void Specials::LaunchSignalFlare(const Stuff::Point3D& pos)
{
//	m_QueuedSignalFlares.push_back(pos);
}

void Specials::LaunchFirework(unsigned int type, const Stuff::Point3D& pos)
{
/*
	if (type > m_FireworksResource.size())
	{
		return;
	}

	Adept::Resource* resource = m_FireworksResource[type];

	if ((GetPlayerVehicle() == 0) ||
		(resource == 0) ||
		(resource->GetResourceID() == ResourceID::Null))
	{
		return;
	}

	GetPlayerVehicle()->CreateEffect(resource->GetResourceID(),pos);
*/
}

void Specials::LaunchFireworks(const Stuff::Point3D& pos, int duration)
{
/*
	m_FireworksStopTime = (Stuff::Time)gos_GetElapsedTime() + (Stuff::Time)duration;
	m_NextFireworkStartTime = (Stuff::Time)gos_GetElapsedTime() + GetTimeToNextFirework();
	m_FireworksOrigin = pos;
*/
}

void Specials::LaunchConfetti()
{
	if (m_ConfettiLaunched == false)
	{
		m_LaunchConfetti = true;
	}
}

void Specials::Update()
{
/*
	if (GetPlayerVehicle() != 0)
	{
		if ((m_FlareResource.GetPointer() != 0) &&
			(m_FlareResource->GetResourceID() != ResourceID::Null))
		{
			while (m_QueuedSignalFlares.size() > 0)
			{
				GetPlayerVehicle()->CreateEffect(m_FlareResource->GetResourceID(),*(m_QueuedSignalFlares.begin()));
				m_QueuedSignalFlares.erase(m_QueuedSignalFlares.begin());
			}
		}

		if (m_LaunchConfetti == true)
		{
			if ((m_ConfettiResource.GetPointer() != 0) &&
				(m_ConfettiResource->GetResourceID() != ResourceID::Null))
			{
				MechWarrior4::MWPlayer* p = Cast_Object(MechWarrior4::MWPlayer*,Adept::Player::GetInstance());
				if ((p != 0) &&
					(p->GetInterface() != 0))
				{
					p->GetInterface()->CreateWeatherEffect(m_ConfettiResource->GetResourceID());
				}
			}

			m_LaunchConfetti = false;
			m_ConfettiLaunched = true;
		}
	}

	if (gos_GetElapsedTime() < m_FireworksStopTime)
	{
		int iters = 0;
		while (m_NextFireworkStartTime < gos_GetElapsedTime())
		{
			LaunchRandomFirework();
			m_NextFireworkStartTime += GetTimeToNextFirework();

			++iters;
			if (iters > 4)
			{
				return;
			}
		}
	}
*/
}

Stuff::Time Specials::GetTimeToNextFirework() const
{
	return (Stuff::Random::GetFraction() * max_delay_between_fireworks);
}

void Specials::LaunchRandomFirework()
{
/*
	Stuff::Point3D pos(m_FireworksOrigin);
	OffsetTargetPoint(pos,max_fireworks_origin_skew);

	LaunchFirework(gos_rand() % m_FireworksResource.size(),pos);
*/
}

void Specials::LaunchFighterSmoke(MechWarrior4::MWObject& mwobject, int smoke_index)
{
/*
	Check_Pointer(this);

	AttachSmoke(mwobject,smoke_index,Stuff::Point3D(-11,0,0));
	AttachSmoke(mwobject,smoke_index,Stuff::Point3D(11,0,0));
*/
}

void Specials::AttachSmoke(MechWarrior4::MWObject& mwobject, int smoke_index, const Stuff::Point3D& offset)
{
	if ((smoke_index > m_FighterSmoke.size()) ||
		(m_FighterSmoke[smoke_index]->DoesResourceExist() == false))
	{
		return;
	}

	MechWarrior4::MWObject::ClassID class_ID;
	class_ID = Adept::Entity::GetClassIDFromDataListID(m_FighterSmoke[smoke_index]->GetResourceID());
	Verify(class_ID != NullClassID);

	LinearMatrix4D initial_position = LinearMatrix4D::Identity;
	initial_position.Multiply(gosFX::Effect_Against_Motion, mwobject.GetElement()->GetNewLocalToParent());

	Adept::Effect::CreateMessage effect_create_message(
		sizeof(Effect::CreateMessage),
		DefaultEventPriority,
		MechWarrior4::MWObject::CreateMessage::DefaultFlags,
		class_ID,
		Effect::DefaultFlags|Effect::LoopFlag,
		m_FighterSmoke[smoke_index]->GetResourceID(),
		initial_position,
		0.0f,
		MechWarrior4::MWObject::ExecutionStateEngine::AlwaysExecuteState,
		NameTable::NullObjectID,
		Entity::DefaultAlignment
	);
	MemoryStream stream(&effect_create_message, effect_create_message.messageLength);

	Entity *entity;
	ReplicatorID trail_id = Connection::Hermit->GetNextReplicatorID();
	entity = mwobject.CreateEntity(&stream, &trail_id, false);
	Check_Object(entity);
	Check_Object(Adept::Map::GetInstance());
	Adept::Map::GetInstance()->AddChild(entity);
	Effect* effect = Cast_Object(Effect*,entity);
	effect->SetFollowEntity(&mwobject);

	effect->effectOffset.BuildTranslation(offset);

	effect->executionState->RequestState(Effect::ExecutionStateEngine::RunningState);
	effect->SyncMatrices(true);
}
