#include "MW4Headers.hpp"

#include "ArtilleryMark.hpp"
#include "Missile.hpp"

#include <Adept\Effect.hpp>
#include <Adept\Map.hpp>
#include <Adept\EntityManager.hpp>
#include <Adept\Site.hpp>

//#############################################################################
//###############################    ArtilleryMark    #########################
//#############################################################################

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ArtilleryMark::ClassData*
	ArtilleryMark::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ArtilleryMark::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			ArtilleryMarkClassID,
			"MechWarrior4::ArtilleryMark",
			BaseClass::DefaultData,
			0, NULL,
			(Entity::Factory)Make,
			(Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
			ExecutionStateEngine::DefaultData,
			(Entity::GameModel::Factory)GameModel::ConstructGameModel,
			NULL,
			(Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
			(Entity::GameModel::ModelWrite)GameModel::WriteToText,
			(Entity::GameModel::ModelSave)GameModel::SaveGameModel
		);
	Register_Object(DefaultData);

	DIRECT_GAME_MODEL_ATTRIBUTE(
		ArtilleryMark__GameModel,
		ArtilleryModelResource,
		artilleryModelResource,
		ResourceID
	);

	DIRECT_GAME_MODEL_ATTRIBUTE(
		ArtilleryMark__GameModel,
		InitialLinearVelocity,
		initialLinearVelocity,
		Vector3D
	);

	DIRECT_GAME_MODEL_ATTRIBUTE(
		ArtilleryMark__GameModel,
		InitialLinearAcceleration,
		initialLinearAcceleration,
		Vector3D
	);

	DIRECT_GAME_MODEL_ATTRIBUTE(
		ArtilleryMark__GameModel,
		DamageAmount,
		damageAmount,
		Scalar
	);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ArtilleryMark::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ArtilleryMark*
	ArtilleryMark::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	Check_Object(message);
	gos_PushCurrentHeap(Heap);
	Check_Object(EntityManager::GetInstance());
	ArtilleryMark *new_entity;
	Entity *entity = EntityManager::GetInstance()->RequestFromArmory(message->dataListID);
	if (entity)
	{
		new_entity = Cast_Object(ArtilleryMark*, entity);
		new_entity->Reuse(message, base_id);
	}
	else
		new_entity = new ArtilleryMark(DefaultData, message, base_id, NULL);
	gos_PopCurrentHeap();
	Check_Object(new_entity);
	return new_entity;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ArtilleryMark::ArtilleryMark(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	StickyMover(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);

	callDownTheFury = false;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ArtilleryMark::~ArtilleryMark()
{
	Check_Object(this);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ArtilleryMark::OnActiveTimeStart()
{
	Check_Object(this);

	callDownTheFury = true;
	UsePostCollision();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ArtilleryMark::CallDownTheFury()
{
	Check_Object(this);

	callDownTheFury = false;
	//
	//---------------------------------------------------------------------
	//This is where we need to drop the bomb on ourselves.  Will this work?
	//---------------------------------------------------------------------
	//
	Check_Object(this);
	const GameModel *model = GetGameModel();
	Check_Object(model);

	if(model->artilleryModelResource != ResourceID::Null)
	{
		//
		//---------------------------------
		//Get the ClassID from the Resource
		//---------------------------------
		//
		ClassID class_ID;
		class_ID = GetClassIDFromDataListID(model->artilleryModelResource);
		Verify(class_ID != NullClassID);

	//	Resource game_model_resource;
	//	GetGameModelResourceFromDataListID(&game_model_resource, model->artilleryModelResource);
	//	const Missile__GameModel *missile_model = Cast_Pointer(Missile__GameModel *, game_model_resource.GetPointer());

		Normal3D target_normal;

		Motion3D initial_velocity = Motion3D::Identity;
		Motion3D initial_acceleration = Motion3D::Identity;
		LinearMatrix4D site_local_to_world;

		//-------------------------
		//Initialize the velocities
		//-------------------------
		//
		Point3D local_to_world, bomb_local_to_world;
		local_to_world = GetLocalToWorld();
		bomb_local_to_world = local_to_world;
		bomb_local_to_world.y += 150.0f;

	//	initial_acceleration.linearMotion = model->initialLinearAcceleration;

	//	Vector3D direction;
	//	direction.Subtract(local_to_world,(Stuff::Point3D)bomb_local_to_world);

		LinearMatrix4D direction_matrix = LinearMatrix4D::Identity;
		direction_matrix.BuildTranslation(bomb_local_to_world);
	//	YawPitchRoll rotation(0.0f, -Pi_Over_2, 0.0f);
	//	direction_matrix.BuildRotation(rotation);

	//	initial_velocity.linearMotion.Multiply(model->initialLinearVelocity, direction_matrix);

		initial_acceleration.linearMotion.x = 0.0f;
		initial_acceleration.linearMotion.y = -14.8f;
		initial_acceleration.linearMotion.z = 0.0f;

		initial_velocity.linearMotion = Vector3D::Identity;
		//
		//--------------------------------
		//Create the Missile CreateMessage
		//--------------------------------
		//

		WeaponMover::CreateMessage projectile_create_message(
			sizeof(Missile::CreateMessage),
			DefaultEventPriority,
			CreateMessage::DefaultFlags,
			class_ID,
			WeaponMover::DefaultFlags,
			model->artilleryModelResource,
			direction_matrix,
			0.0f,
			Missile::ExecutionStateEngine::LinearDragMotionState,
			NameTable::NullObjectID,
			Entity::DefaultAlignment,
			initial_velocity,
			initial_acceleration,
			model->damageAmount,
			0.0f,
			1200,
// MSL 5.03 Min Distance
//			model->minDistance,
			inflictingEntityID,
			splashRadius,
			percentageOfDamageToDirectHit,
			minPercentageOfDamageToSphereHit,
			maxPercentageOfDamageToSphereHit,
			itemID
		);
		MemoryStream stream(&projectile_create_message, projectile_create_message.messageLength);

		Entity *entity;
		ReplicatorID projectile_id = Connection::Hermit->GetNextReplicatorID();
		entity = CreateEntity(&stream, &projectile_id, false);
		Check_Object(entity);
		Map::GetInstance()->AddChild(entity);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ArtilleryMark::PostCollisionExecute(Time till)
{
	Check_Object(this);
	POSTCOLLISION_LOGIC("ArtilleryMark");

	if(callDownTheFury)
		CallDownTheFury();

	StickyMover::PostCollisionExecute(till);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ArtilleryMark::OnActiveTimeEnd()
{
	Check_Object(this);
}

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


