//===========================================================================//
// File: Replicator.cpp                                                      //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               // 
// --------  ---  ---------------------------------------------------------- //
// 11/29/94  JMA  Initial coding.                                            //
// 08/25/97  JMA  Infrastructure changes												  //
// 08/25/97  ECH	Infrastructure changes												  //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-97, Virtual World Entertainment, Inc.                  //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include "AdeptHeaders.hpp"

#include "Replicator.hpp"
#include "Connection.hpp"

//#############################################################################
//##########################    Replicator    #################################
//#############################################################################

ReplicatorID
	ReplicatorID::Null;

Replicator::ClassData
	*Replicator::DefaultData = NULL;

const Receiver::MessageEntry
	Replicator::MessageEntries[]=
{
	MESSAGE_ENTRY(Replicator, Destroy)
};

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Replicator::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			ReplicatorClassID,
			"Adept::Replicator",
			Receiver::DefaultData,
			ELEMENTS(MessageEntries), MessageEntries,
			NULL,
			NULL
		);
	Register_Object(DefaultData);
}

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

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

	//
	//---------------------------------------------------------------------
	// Make sure there is enough room for the factory request on the stream
	//---------------------------------------------------------------------
	//
	stream->AllocateBytes(sizeof(CreateMessage));
	CreateMessage *message =
		Cast_Pointer(CreateMessage*, stream->GetPointer());
	message->messageLength = sizeof(*message);

	//
	//---------------------------
	// Create the factory request
	//---------------------------
	//
	message->messageID = Connection::ReplicateMessageID;
	message->messagePriority = DefaultEventPriority;
	message->messageFlags = CreateMessage::DefaultFlags;
	message->replicatorFlags = replicatorFlags;
	message->replicatorID.connectionID = 0;
	message->replicatorID.localID = 1;
	message->classID = GetClassID();
	return message;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Replicator::Replicator(
	ClassData *class_data,
	const CreateMessage *message,
	ReplicatorID *base_id
):
	Receiver(class_data)
{
	Check_Pointer(this);
	Check_Object(message);

	//
	//---------------------------------
	// Extract our data from the stream
	//---------------------------------
	//
	Verify(message->classID == GetClassID());
	replicatorFlags = message->replicatorFlags;

	//
	//---------------------
	// Get the replicant ID
	//---------------------
	//
	replicatorID = *base_id;
	++*base_id;
	owningConnection =
		Network::GetInstance()->GetConnection(replicatorID.connectionID);
	Check_Object(owningConnection);

	if(owningConnection == Connection::Hermit)
	{
		Verify(GetReplicatorMode() == HermitMode);
	}



	// here we go...
	// if we are the server than we own everything..


	if (owningConnection != Connection::Hermit)
	{
		SetReplicatorMode(MasterMode);


		Verify(GetReplicatorMode() != HermitMode);

		if (Network::GetInstance()->AmIServer())
		{
			
			// if we don't own it and it is a master it will be the ServerMasterMode ( the receiver of a ClientMaster )
			if ((owningConnection != Connection::Local) && (owningConnection != Connection::Hermit))
			{
				if (GetReplicatorMode() == MasterMode)
					SetReplicatorMode(ServerMasterMode);
			}
			
		}
		else
		{
			// we are a client so we don't own anything.
			
			if ((owningConnection == Connection::Local) && (GetReplicatorMode() == MasterMode))
			{
				SetReplicatorMode(ClientMasterMode);
			}
			else if ((owningConnection != Connection::Local) && GetReplicatorMode() == MasterMode)
			{
				SetReplicatorMode(ReplicantMode);
			}
		}
	}
	//
	//----------------------------
	// Hook up to the host manager
	//----------------------------
	//
	owningConnection->AddReplicator(this);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Replicator::~Replicator()
{
	
	DESTRUCTOR("Replicator");

	//
	//--------------------------------------------------------------
	// Notify replicator manager, the connection to the host manager 
	// is removed automatically
	//--------------------------------------------------------------
	//
	if (owningConnection)
	{

		Check_Object(owningConnection);
		owningConnection->ReplicatorDestroyed(this);
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Replicator::Reuse(
		const Replicator::CreateMessage *message,
		ReplicatorID *base_id
	)
{
	Check_Pointer(this);
	Check_Object(message);

	//
	//---------------------------------
	// Extract our data from the stream
	//---------------------------------
	//
	Verify(message->classID == GetClassID());
	replicatorFlags = message->replicatorFlags;

	//
	//---------------------
	// Get the replicant ID
	//---------------------
	//
	replicatorID = *base_id;
	++*base_id;
	Verify(!owningConnection);
	owningConnection =
		Network::GetInstance()->GetConnection(replicatorID.connectionID);
	Check_Object(owningConnection);

	if(owningConnection == Connection::Hermit)
	{
		Verify(GetReplicatorMode() == HermitMode);
	}



	// here we go...
	// if we are the server than we own everything..


	if (owningConnection != Connection::Hermit)
	{
		Verify(GetReplicatorMode() != HermitMode);

		SetReplicatorMode(MasterMode);


		if (Network::GetInstance()->AmIServer())
		{
			
			// if we don't own it and it is a master it will be the ServerMasterMode ( the receiver of a ClientMaster )
			if ((owningConnection != Connection::Local) && (owningConnection != Connection::Hermit))
			{
				if (GetReplicatorMode() == MasterMode)
					SetReplicatorMode(ServerMasterMode);
			}
			
		}
		else
		{
			// we are a client so we don't own anything.
			
			if ((owningConnection == Connection::Local) && (GetReplicatorMode() == MasterMode))
			{
				SetReplicatorMode(ClientMasterMode);
			}
			else if ((owningConnection != Connection::Local) && GetReplicatorMode() == MasterMode)
			{
				SetReplicatorMode(ReplicantMode);
			}
		}
	}
	//
	//----------------------------
	// Hook up to the host manager
	//----------------------------
	//
	owningConnection->AddReplicator(this);
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Replicator::Respawn(
		const Replicator::CreateMessage *message
	)
{
	Check_Pointer(this);
	Check_Object(message);

	
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Replicator::Dispatch(const Receiver::Message *incoming)
{
	Check_Object(this);
	Check_Object(incoming);


	STOP(("Replicator::Distpatch has been disabled for networking.  Please use Receiver::Receive instead!"));

#if 0
	//
	//------------------------------------------------------
	// Call Receiver if it is not a replicator aware message
	//------------------------------------------------------
	//
	if (incoming->messageID < Receiver::NextMessageID)
		Receiver::Dispatch(incoming);

	//
	//---------------------------------------------
	// Initialize the replicator information fields
	//---------------------------------------------
	//
	const Message *message = Cast_Pointer(const Message*, incoming);
	Check_Object(message);

	//
	//-------------------------------------------------------------------
	// If this is a replicant instance, reroute the message to the master
	//-------------------------------------------------------------------
	//
	if (GetReplicatorMode() == ReplicantMode)
	{
		Check_Object(owningConnection);
		owningConnection->SendToMaster(this, message);
		return;
	}

	//
	//--------------------------------------------
	// Otherwise, go ahead and receive the message
	//--------------------------------------------
	//
	Receiver::Receive(message);
#endif
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Replicator::DispatchToReplicants(const Message *message)
{
	Check_Object(this);
	Check_Object(message);

	Check_Object(owningConnection);
	owningConnection->BroadcastToReplicants(this, message);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Replicator::DestroyMessageHandler(const DestroyMessage *message)
{
	Check_Object(this);
	Check_Object(message);
	Verify(message->messageID == DestroyMessageID);
	delete this;
}

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

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