//===========================================================================//
// File: Replicator.hpp                                                      //
//---------------------------------------------------------------------------//
//   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               //
//===========================================================================//

#pragma once

#include "Adept.hpp"
#include "Receiver.hpp"
#include "Connection.hpp"

namespace Adept {

	//##########################################################################
	//##################    Replicator::CreateMessage    #######################
	//##########################################################################

	class Replicator__ClassData;

	class Replicator__CreateMessage:
		public Connection__Message
	{
	public:
		Stuff::RegisteredClass::ClassID
			classID;
		int
			replicatorFlags;
		ReplicatorID
			replicatorID;

		Replicator__CreateMessage(
			size_t length,
			int priority,
			int message_flags,
			Stuff::RegisteredClass::ClassID class_id,
			int replicator_flags
		):
			Connection__Message(
				Connection::ReplicateMessageID,
				length,
				priority,
				message_flags
			),
			classID(class_id),
			replicatorFlags(replicator_flags),
			replicatorID(ReplicatorID::Null)
				{}

		class Script
		{
		public:
			void
				TestInstance() const
					{}

			Stuff::MemoryStream
				*messageStream;
			Stuff::Page
				*instancePage;
			ReplicatorID
				*baseID;
			Replicator__ClassData
				*classData;
			Resource
				modelResource;
		};

		typedef void
			(*Factory)(Script *script);
		static void
			ConstructCreateMessage(Script *script);
	};

	//##########################################################################
	//#####################    Replicator::Message    ##########################
	//##########################################################################

	class Replicator__Message:
		public Receiver__Message
	{
	public:
		ReplicatorID
			replicatorID;

		enum {
			ReplicantCanReceiveBit = 1<<Receiver__Message::NextBit,
			NextBit
		};

		enum {
			ReplicantCanReceiveFlag = 1 << ReplicantCanReceiveBit
		};

		Replicator__Message(
			Receiver::MessageID message_id,
			size_t length,
			int priority,
			int flags,
			const ReplicatorID &replicator_id
		):
			Receiver__Message(message_id, length, priority, flags),
			replicatorID(replicator_id)
				{}
	};

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

	class Replicator__ClassData;
	typedef Replicator__Message Replicator__DestroyMessage;

	class _declspec(novtable) Replicator:
		public Receiver
	{
		friend class Connection;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Inheritance support
	//
	public:
		typedef Replicator__ClassData		ClassData;
		typedef Replicator__Message			Message;
		typedef Replicator__CreateMessage	CreateMessage;
		typedef Replicator__DestroyMessage	DestroyMessage;

	public:
		static void
			InitializeClass();
		static void
			TerminateClass();
		ClassData*
			GetClassData();
		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		typedef Replicator*
			(*Factory)(
				const CreateMessage *message,
				ReplicatorID* base_id
			);

		virtual CreateMessage*
			SaveMakeMessage(Stuff::MemoryStream *stream, ResourceFile *res_file);

	protected:
		Replicator(
			ClassData *class_data,
			const CreateMessage *message,
			ReplicatorID *base_id
		);
		~Replicator();

		void
			Reuse(
				const CreateMessage *message,
				ReplicatorID *base_id
			);

		void
			Respawn(
				const CreateMessage *message
			);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Message Support
	//
	public:
		enum {
			DestroyMessageID = Receiver::NextMessageID,
			NextMessageID
		};

		void
			Dispatch(const Receiver::Message *what);
		void
			DispatchToReplicants(const Message *what);

		void
			DestroyMessageHandler(const DestroyMessage *message);

	protected:
		static const MessageEntry
			MessageEntries[];

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Flag Support
	//
	public:
		enum {
			ReplicantFlagBit=0,
			NextFlagBit=3
		};

		enum ReplicatorMode {
			MasterMode			= 0<<ReplicantFlagBit,
			IndependentMode		= 1<<ReplicantFlagBit,
			HermitMode			= 2<<ReplicantFlagBit,
			ReplicantMode		= 3<<ReplicantFlagBit,
			ClientMasterMode	= 4<<ReplicantFlagBit,
			ServerMasterMode	= 5<<ReplicantFlagBit
		};

		enum {
			ReplicatorModeMask	= (7<<ReplicantFlagBit),
			DefaultFlags		= 0
		};


		ReplicatorMode
			GetReplicatorMode()
				{Check_Object(this); return static_cast<ReplicatorMode>(replicatorFlags & ReplicatorModeMask);}
		void
			SetReplicatorMode(ReplicatorMode mode)
				{Check_Object(this); replicatorFlags &= ~ReplicatorModeMask; replicatorFlags |= mode;}

		int
			replicatorFlags;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Ownership support
	//
	public:
		const ReplicatorID&
			GetReplicatorID()
				{Check_Object(this); return replicatorID;}

		Connection*
			GetOwner()
				{Check_Object(this); return owningConnection;}

	protected:
		ReplicatorID
			replicatorID;
		Connection*
			owningConnection;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test Support
	//
	public:
		void
			TestInstance();
		static bool
			TestClass();
	};

	//##########################################################################
	//###################    Replicator::ClassData    ##########################
	//##########################################################################

	class Replicator__ClassData:
		public Receiver__ClassData
	{
	public:
		Replicator__ClassData(
			Stuff::RegisteredClass::ClassID class_id,
			const char* class_name,
			Receiver::ClassData *parent_class,
			int message_count,
			const Receiver::MessageEntry *message_handlers,
			Replicator::Factory replicator_factory,
			Replicator::CreateMessage::Factory message_factory
		):
			Receiver__ClassData(
				class_id,
				class_name,
				parent_class,
				message_count,
				message_handlers
			),
			replicatorFactory(replicator_factory),
			messageFactory(message_factory)
				{}

		Replicator::Factory
			replicatorFactory;
		Replicator::CreateMessage::Factory
			messageFactory;

		void
			TestInstance();
	};

	inline Replicator::ClassData*
		Replicator::GetClassData()
	{
		return Cast_Pointer(ClassData*, classData);
	}

}
