#include "MW4Headers.hpp"

#include "ObservationVehicle.hpp"
#include <Adept\CollisionGrid.hpp>
#include <Adept\EntityClassData.hpp>
#include <ElementRenderer\Element.hpp>

//#############################################################################
//###############################    ObservationVehicle    ##############################
//#############################################################################

ObservationVehicle::ClassData* ObservationVehicle::DefaultData = NULL;


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

	
	Register_Object(DefaultData);
}

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

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ObservationVehicle* ObservationVehicle::Make(CreateMessage *message,ReplicatorID *base_id)
{
	Check_Object(message);
	ObservationVehicle *new_entity =
		new ObservationVehicle(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ObservationVehicle::ObservationVehicle(ClassData *class_data,CreateMessage *message,ReplicatorID *base_id,ElementRenderer::Element *element):
	Vehicle(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);
	//Make sure it doesn't show up on sensor
	SetVisibleOnSensors(false);
	//executionState->RequestState(ExecutionStateEngine::DrivingMotionState);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ObservationVehicle::~ObservationVehicle()
{
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void ObservationVehicle::TurnOn (void)
{
	lastParameterization = gos_GetElapsedTime ();
	executionState->RequestState(ExecutionStateEngine::DrivingMotionState);
}


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

void ObservationVehicle::TestInstance() const
{
	Verify(IsDerivedFrom(DefaultData));
}



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

void ObservationVehicle::PreCollisionExecute(Stuff::Time till)
{
	Check_Object(this);
	PRECOLLISION_LOGIC("ObservationVehicle");
	
	UsePostCollision ();


	// find the ground...
	
	//
	//----------------------------------------------
	// Cast a ray down to see what we are driving on
	//----------------------------------------------
	//
	
	LinearMatrix4D new_local_to_world;
	UnitQuaternion rotation;
	rotation = GetLocalToWorld();
	Point3D position;
	position = GetLocalToWorld();


	Stuff::Line3D line;
	line.m_length = 1000.0f;
	line.m_direction = Vector3D::Down;
	line.m_origin = position;
	line.m_origin.y += 500.0f;
	Stuff::Normal3D normal;
	CollisionQuery query(&line, &normal, CanBeWalkedOnFlag, this);
	Check_Object(CollisionGrid::Instance);


	if (CollisionGrid::Instance->ProjectLine(&query))
	{
		line.FindEnd(&position);
		position.y += 4.0f;
	}

	new_local_to_world.BuildTranslation(position);
	new_local_to_world.BuildRotation(rotation);

	SetNewLocalToParent(new_local_to_world);


	BaseClass::PreCollisionExecute (till);
		
}
