//===========================================================================//
// File:	entity2.hh                                                          //
// Project: MUNGA           Brick: Entity Manager                            //
// Contents: Interface specification for entity class                        //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 11/29/94  JMA  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc.                     //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "Adept.hpp"

namespace Adept {class ReplicatorID;}

#if !defined(Spew)
	void
		Spew(
			const char* group,
			const Adept::ReplicatorID& v
		);
#endif

namespace GetHashFunctions {
	unsigned
		GetHashValue(const Adept::ReplicatorID &value);
}

namespace Adept {

	//##########################################################################
	//#########################    ReplicatorID    #############################
	//##########################################################################

	class ReplicatorID
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Constructors
	//
	public:
		ReplicatorID():
			connectionID(0),
			localID(0)
				{Check_Pointer(this);}

		ReplicatorID(const ReplicatorID& id):
			connectionID(id.connectionID),
			localID(id.localID)
				{Check_Pointer(this); Check_Object(&id);}

		explicit ReplicatorID(BYTE connection_id):
			connectionID(connection_id),
			localID(0)
				{Check_Pointer(this);}

		ReplicatorID(
			BYTE connection_id,
			WORD local_id
		):
			connectionID(connection_id),
			localID(local_id)
				{Check_Pointer(this);}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// ID mathematics
	//
	public:
		static ReplicatorID
			Null;

		bool
			operator!() const
				{Check_Object(this); return operator==(Null);}

		ReplicatorID&
			operator=(const ReplicatorID& id)
				{
					Check_Pointer(this); Check_Object(&id);
					connectionID = id.connectionID; localID = id.localID;
					return *this;
				}

		ReplicatorID&
			operator+=(const ReplicatorID& id)
				{
					Check_Object(this); Check_Object(&id);
					connectionID = static_cast<BYTE>(connectionID + id.connectionID);
					localID = static_cast<WORD>(localID + id.localID);
					return *this;
				}

		ReplicatorID&
			operator+=(WORD span)
				{Check_Object(this); localID = static_cast<WORD>(localID + span); return *this;}

		ReplicatorID&
			operator++()
				{Check_Pointer(this); ++localID; return *this;}

		bool
			operator<(const ReplicatorID& id) const
				{
					Check_Object(this); Check_Object(&id);
					return
						(connectionID == id.connectionID) ?
							(localID < id.localID) :
							(connectionID < id.connectionID);
				}

		bool
			operator<=(const ReplicatorID& id) const
				{
					Check_Object(this); Check_Object(&id);
					return
						(connectionID == id.connectionID) ?
							(localID <= id.localID) :
							(connectionID < id.connectionID);
				}

		bool
			operator>(const ReplicatorID& id) const
				{
					Check_Object(this); Check_Object(&id);
					return
						(connectionID == id.connectionID) ?
							(localID > id.localID) :
							(connectionID > id.connectionID);
				}

		bool
			operator>=(const ReplicatorID& id) const
				{
					Check_Object(this); Check_Object(&id);
					return
						(connectionID == id.connectionID) ?
							(localID >= id.localID) :
							(connectionID > id.connectionID);
				}

		bool
			operator==(const ReplicatorID& id) const
				{
					Check_Object(this); Check_Object(&id);
					return (connectionID == id.connectionID && localID == id.localID);
				}

		bool
			operator!=(const ReplicatorID& id) const
				{
					Check_Object(this); Check_Object(&id);
					return
						(connectionID != id.connectionID || localID != id.localID);
				}

		#if !defined(Spew)
			friend void
				::Spew(
					const char* group,
					const ReplicatorID& v
				)
					{SPEW((group, "%d:%d+", v.connectionID, v.localID));}
		#endif

		friend unsigned
			GetHashFunctions::GetHashValue(const ReplicatorID &value)
				{
					//
					// Verify that the unsigned is 32 bits wide,
					// Hash value is first 16 bits of connectionID and first 16 bits 
					// of localID
					//
					Verify(sizeof(unsigned) == sizeof(DWORD));
					return (value.connectionID << 16) | value.localID;
				}

		BYTE
			connectionID;
		WORD
			localID;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Testing
	//
	public:
		void
			TestInstance() const
				{}
	};

}

namespace MemoryStreamIO {

	inline Stuff::MemoryStream&
		Read(
			Stuff::MemoryStream *stream,
			Adept::ReplicatorID *output
		)
			{return stream->ReadBytes(output, sizeof(*output));}

	inline Stuff::MemoryStream&
		Write(
			Stuff::MemoryStream* stream,
			const Adept::ReplicatorID *input
		)
			{return stream->WriteBytes(input, sizeof(*input));}

}


