//===========================================================================//
// File:	Driver.cpp																	     //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 03/08/99  DPB  Created file                          //
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include "AdeptHeaders.hpp"

#include "Driver.hpp"
#include "DropZone.hpp"
#include "EntityManager.hpp"
#include "Map.hpp"
#include "Mover.hpp"

//#############################################################################
//###############################    Driver      ##############################
//#############################################################################

Driver::ClassData*
	Driver::DefaultData = NULL;


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Driver::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			DriverClassID,
			"Adept::Driver",
			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);
}

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

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Replicator::CreateMessage*
	Driver::SaveMakeMessage(MemoryStream *stream, ResourceFile *res_file)
{
	Check_Object(this);
	Check_Object(stream);

	stream->AllocateBytes(sizeof(CreateMessage));
	BaseClass::SaveMakeMessage(stream, res_file);
	CreateMessage *message =
		Cast_Pointer(CreateMessage*, stream->GetPointer());
	message->messageLength = sizeof(*message);

	Verify(message->initialAge != 0.0f);
	message->dropZone = dropZone;
	return message;
}

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

	isDropped = false;
	//
	//------------------------------------------------------------------------
	//Vehicle needs to be set at a higher level.  Player creates and AI links.
	//------------------------------------------------------------------------
	//
	vehicle = NULL;

	UsePostCollision();

	dropZone = message->dropZone;

	//
	//---------------------------------------------------
	// Only ask for a dropzone if we haven't executed yet
	//---------------------------------------------------
	//
	if (owningConnection == Connection::Local)
	{
		if (message->initialAge != 0.0f)
		{
			ElementRenderer::Element *element = vehicle->GetElement();
			Check_Object(element);
			ReceiveDropZone(element->GetNewLocalToParent());
		}
		else
		{

			if(dropZone != NameTable::NullObjectID)
			{
				DropZone *zone;
				zone = EntityManager::GetInstance()->GetDropZone(dropZone);
				Check_Object(zone);
			
				Stuff::LinearMatrix4D drop_location = Stuff::LinearMatrix4D::Identity;

				drop_location = zone->RequestDrop();

				ReceiveDropZone(drop_location);

			}
		}
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Driver::Respawn(Entity::CreateMessage *message)
{
	Check_Object(this);
	Check_Object(message);

	BaseClass::Respawn(message);

	CreateMessage *driver_message = Cast_Pointer(CreateMessage *, message);
	isDropped = false;
	//
	//------------------------------------------------------------------------
	//Vehicle needs to be set at a higher level.  Player creates and AI links.
	//------------------------------------------------------------------------
	//

	UsePostCollision();
	dropZone = driver_message->dropZone;

	//
	//---------------------------------------------------
	// Only ask for a dropzone if we haven't executed yet
	//---------------------------------------------------
	//
	if (owningConnection == Connection::Local)
	{
		if (message->initialAge != 0.0f)
		{
			ElementRenderer::Element *element = vehicle->GetElement();
			Check_Object(element);
			ReceiveDropZone(element->GetNewLocalToParent());
		}
		else
		{
			if(dropZone != NameTable::NullObjectID)
			{
				DropZone *zone;
				zone = EntityManager::GetInstance()->GetDropZone(dropZone);
				Check_Object(zone);
			
				Stuff::LinearMatrix4D drop_location = Stuff::LinearMatrix4D::Identity;

				drop_location = zone->RequestDrop();

				ReceiveDropZone(drop_location);

			}
		}
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Driver::~Driver()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Driver::ReceiveDropZone(const Stuff::LinearMatrix4D& drop_location)
{
	STOP(("Driver::ReceiveDropZoneMessageHandler : NOT IMPLIMENTED"));

	Check_Object(this);

	isDropped = true;

	vehicle->SetNewLocalToParent(drop_location);
	SyncMatrices(true);

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

	
	SetNewLocalToParent(vehicle->GetLocalToWorld());

	SyncMatrices(true);
	BaseClass::PostCollisionExecute(till);
}


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

Stuff::LinearMatrix4D
	Driver::GetEyePoint()
{
	return vehicle->GetLocalToWorld();
}


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

