//===========================================================================//
// File:	interest.hh                                                         //
// Project: MUNGA           Brick: Interest Manager	                       //
// Contents: Interface specifications for interest manager						  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  -----------------------------------------------------------//
// 11/04/94  ECH  Initial coding.                                            //
// 11/29/94  JMA  Changed Identities to IDs                                  //
// 02/10/95  CPB  Added GaugeInterestType                                    //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc.                //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#if !defined(INTEREST_HPP)
# define INTEREST_HPP

#	if !defined(NETWORK_HPP)
#		include <network.hpp>
#	endif

#	if !defined(HOST_HPP)
#		include <host.hpp>
#	endif

#	if !defined(INTORGN_HPP)
#		include <intorgn.hpp>
#	endif

#	if !defined(ENTITYID_HPP)
#		include <entityid.hpp>
#	endif

	class Renderer;
	class Entity;
	class Entity__MakeMessage;
	class Entity__UpdateMessage;
	class Entity__DestroyEntityMessage;
	class Entity__Message;

	//##########################################################################
	//#######################    InterestManager    ############################
	//##########################################################################

	#define INTERESTMANAGER_MESSAGE_BUFFER_SIZE (1536)

	class Mission;

	class InterestManager__EntitySubscribeToUpdatesMessage;
	class InterestManager__EntityBroadcastToReplicantsMessage;
	class InterestManager__EntityNewInterestZoneMessage;
	class InterestManager__HostInterestArenaChangedMessage;
	class InterestManager__InterestZoneDeltaMessage;

	//
	//--------------------------------------------------------------------------
	// InterestManager
	//
	// Entity types relevant to the interest managers operation:
	//
	// Static Entity (!replicated, !executing, !moving, trapped, map, id)
	// - an entity that is not replicated, it does not execute or move.
	// It is a component of the map and therefore trapped within its
	// interest zone.  It has a preallocated entity id.  (rock, fence, wall)
	//
	// Dynamic Entity (replicated, executing, moving, !trapped, !map, !id)
	// - an entity that may be replicated.  It executes upon its host
	// machine.  It is also moves freely, crossing interest zones if it
	// wishes.  It is not a component of the map and can not be given a
	// preallocated entity id.  (VTV, Mech, missile)
	//
	// Dynamic Trapped Entity (replicated, executing, moving, trapped, !map, !id)
	// - an entity that may be replicated.  It executes upon its host
	// machine.  It may move but not out of its interest zone.  It is not
	// a component of the map and can not be given a preallocated entity id.
	// (mines, burning husk of Mech)
	//
	// Dynamic Map Entity (replicated, executing, moving, !trapped, map, id)
	// - an entity that may be replicated.  It executes upon its host machine.
	// It is also moves freely, crossing interest zones if it wishes.  It
	// is a component of the map and can be given a preallocated entity id.
	// (The ork that activates upon entering the dungeon and then follows you,
	// the one moon around the planet that orbits once every 24 hours)
	//
	// Dynamic Trapped Map Entity (replicated, executing, moving, trapped, map, id)
	// - an entity that may be replicated.  It executes upon its host machine.
	// It is also moves freely, but may not change interest zones.  It is a
	// component of the map and can be given a preallocated entity id.
	// (The swinging crane, the RP door)
	//--------------------------------------------------------------------------
	//

	class InterestManager:
		public NetworkClient
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction, Destruction, and Testing
	//
	public:
		InterestManager();
		~InterestManager();

		Logical
			TestInstance() const;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Execution control
	//
	public:
		virtual void
			LoadInterestArenas(Mission *mission);
		virtual void
			LoadMission(Mission *mission);
		void
			LoadMapStream(
				MemoryStream *map_stream,
				const Origin& root,
				EntityID& static_id,
            int &landmark_id
			);

		virtual void
			Shutdown();

		void
			Execute();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Interest Origin methods
	//
	public:
		//
		//-----------------------------------------------------------------------
		// AdoptInterestOrigin
		//
		// Asserts that the entity is a origin of interest of a specified
		// type (example: visual, auditory, radar).  Traversals of the interest
		// lattice are performed with respect to this origin and may be
		// performed with different algorithms depending upon type.  The
		// Lattice is traversed to a particular "depth" or "cost" for a
		// specific interest type and may be calibrated with the
		// DepthCalibration parameter.
		//-----------------------------------------------------------------------
		//
		void
			AdoptInterestOrigin(InterestOrigin *interestOrigin);

		//
		//-----------------------------------------------------------------------
		// OrphanInterestOrigin
		//-----------------------------------------------------------------------
		//
		void
			OrphanInterestOrigin(InterestOrigin *interest_origin);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Entity methods
	//
	public:
		//
		//-----------------------------------------------------------------------
		// NotifyOfEntityCreation
		//-----------------------------------------------------------------------
		//
		void
			NotifyOfEntityCreation(
				Entity *entity,
				Entity__MakeMessage *creation_message
			);

		//
		//-----------------------------------------------------------------------
		// NotifyOfEntityDestruction
		//
		// This method is called to notify the interest manager that a
		// entity has been destroyed.
		//-----------------------------------------------------------------------
		//
		void
			NotifyOfEntityDestruction(Entity *entity);

		//
		//-----------------------------------------------------------------------
		// EntityUpdateInterestZone
		//
		// This method is called if the entity may have changed the
		// interest zone that it is in.  This is used by the update
		// manager.
		//-----------------------------------------------------------------------
		//
		void
			EntityUpdateInterestZone(Entity *entity);

		//
		//-----------------------------------------------------------------------
		// EntityForceToInteresting
		//
		// This forces the interest manager to treat the entity as
		// interesting.
		//
		// HACK - Is effect local?  Is the entity forced to be
		// interesting on just this host?  Or, does the effect pervade
		// all hosts?
		//-----------------------------------------------------------------------
		//
		void
			EntityForceToInteresting(Entity *entity);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Accesors for interest lattice manager
	//
	public:
		InterestLatticeManager*
			GetInterestLatticeManager();

		InterestZone*
			GetInterestZone(InterestZoneID interestZoneID);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//  Message Support
	//
	public:
		//
		// Message IDs
		//
		enum
		{
			//
			//--------------------------------------------------------------------
			// Sent by an interest manager to itself and others when it has been
			// notified that a new dynamic entity has been created on the host
			// machine.
			//--------------------------------------------------------------------
			//
			NewDynamicEntityMessageID = NetworkClient::NextMessageID,

			#if 0
			//
			//--------------------------------------------------------------------
			// Sent by an interest manager to itself and others when it has been
			// notified that a new dynamic map entity has been created on the
			// host machine.
			//--------------------------------------------------------------------
			//
			NewMapEntityMessageID,
			#endif

			//
			//--------------------------------------------------------------------
			// Sent by an interest manager to itself and others when it has been
			// notified that a entity is under going deletion.
			//--------------------------------------------------------------------
			//
			DestroyDynamicEntityMessageID,

			//
			//--------------------------------------------------------------------
			// Message is sent to the host of the original (serving) entity that
			// the host id wishes to be on the entities update list.
			//--------------------------------------------------------------------
			//
			EntitySubscribeToUpdatesMessageID,

			//
			//--------------------------------------------------------------------
			// Sent by the interest manager to itself and others when a hosted
			// entity needs to send updates to its replicants.
			//--------------------------------------------------------------------
			//
			EntityUpdateReplicantsMessageID,

			//
			//--------------------------------------------------------------------
			// Sent by the interest manager to itself and others when a hosted
			// entity needs to broadcast a message to its replicants.
			//--------------------------------------------------------------------
			//
			EntityBroadcastToReplicantsMessageID,

			//
			//--------------------------------------------------------------------
			// Sent by the interest manager to itself and others when a hosted
			// entity has changed interest zones.
			//--------------------------------------------------------------------
			//
			EntityNewInterestZoneMessageID,

			//
			//--------------------------------------------------------------------
			// Sent by the interest manager to others when its interest arena has
			// changed.
			//--------------------------------------------------------------------
			//
			HostInterestArenaChangedMessageID,

			//
			//--------------------------------------------------------------------
			// Tells interest managers of a change to a interest zone.  This is
			// for the purpose of creating and destroying Dynamic Map Entities.
			// The creation time stamp is used by the interest manager to resolve
			// synchronization problems.
			//--------------------------------------------------------------------
			//
			InterestZoneDeltaMessageID,

			NextMessageID
		};

		//
		// Message types
		//
		typedef Entity__MakeMessage
			NewDynamicEntityMessage;
		typedef Entity__DestroyEntityMessage
			DestroyDynamicEntityMessage;
		typedef Entity__UpdateMessage
			EntityUpdateReplicantsMessage;

		typedef InterestManager__EntitySubscribeToUpdatesMessage
			EntitySubscribeToUpdatesMessage;
		typedef InterestManager__EntityBroadcastToReplicantsMessage
			EntityBroadcastToReplicantsMessage;
		typedef InterestManager__EntityNewInterestZoneMessage
			EntityNewInterestZoneMessage;
		typedef InterestManager__HostInterestArenaChangedMessage
			HostInterestArenaChangedMessage;
		typedef InterestManager__InterestZoneDeltaMessage
			InterestZoneDeltaMessage;

		//
		//-----------------------------------------------------------------------
		// NewDynamicEntityHandler
		//-----------------------------------------------------------------------
		//
		void
			NewDynamicEntityHandler(NewDynamicEntityMessage *message);

		//
		//-----------------------------------------------------------------------
		// DestroyEntityHandler
		//-----------------------------------------------------------------------
		//
		void
			DestroyDynamicEntityHandler(DestroyDynamicEntityMessage *message);

		//
		//-----------------------------------------------------------------------
		// EntitySubscribeToUpdates & EntitySubscribeToUpdatesHandler
		//-----------------------------------------------------------------------
		//
		void
			EntitySubscribeToUpdates(
				EntityID entity_ID,
				HostID master_host,
				HostID replicant_host
			);
		void
			EntitySubscribeToUpdatesHandler(
				EntitySubscribeToUpdatesMessage *message
			);

		//
		//-----------------------------------------------------------------------
		// EntityUpdateReplicants & EntityUpdateReplicantsHandler
		//
		// If the entity has any subscribers then send then update to subscribers.
		//-----------------------------------------------------------------------
		//
		void
			EntityUpdateReplicants(
				Entity *entity,
				Entity__UpdateMessage *update_message
			);
		void
			EntityUpdateReplicantsHandler(
				EntityUpdateReplicantsMessage *update_message
			);

		//
		//-----------------------------------------------------------------------
		// EntityBroadcastToReplicants & EntityBroadcastToReplicantsHandler
		//
		// If the entity has any subscribers then send then update to subscribers.
		//-----------------------------------------------------------------------
		//
		void
			EntityBroadcastToReplicants(
				Entity *entity,
				Entity__Message *broadcast_message
			);
		void
			EntityBroadcastToReplicantsHandler(
				EntityBroadcastToReplicantsMessage *broadcast_message
			);

		//
		//-----------------------------------------------------------------------
		// EntityNewInterestZoneHandler
		//-----------------------------------------------------------------------
		//
		void
			EntityNewInterestZoneHandler(
				EntityNewInterestZoneMessage *message
			);

		//
		//-----------------------------------------------------------------------
		// HostInterestArenaChanged
		//-----------------------------------------------------------------------
		//
		void
			HostInterestArenaChangedHandler(
				HostInterestArenaChangedMessage *message
			);

		//
		//-----------------------------------------------------------------------
		// InterestZoneDelta
		//-----------------------------------------------------------------------
		//
		void
			InterestZoneDeltaHandler(
				InterestZoneDeltaMessage *message
			);

		//
		//-----------------------------------------------------------------------
		// LoadResourceFinished
		//-----------------------------------------------------------------------
		//
		void
			LoadResourceFinishedHandler(Message *message);

		//
		//-----------------------------------------------------------------------
		// Shared Data and message tables
		//-----------------------------------------------------------------------
		//
		static Derivation
			ClassDerivations;
		static SharedData
			DefaultData;

		static const HandlerEntry
			MessageHandlerEntries[];
		static MessageHandlerSet
			MessageHandlers;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Creation and Interest Event Posting
	//
	public:
		void
			PostRendererEvent(
				Entity *entity,
				Renderer *renderer,
				Receiver::Message *message
			);

	private:
		void
			PostCreationEvent(Receiver::Message *message);
		void
			PostUpdateEvent(
				Entity *entity,
				Receiver::Message *message
			);
		void
			PostDestructionEvent(
				Entity *entity,
				Receiver::Message *message
			);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Private entity creation and destruction management
	//
	private:
		void
			StaticEntityCreation(
				Entity *entity,
				Entity__MakeMessage *creation_message
			);
		void
			DynamicEntityCreation(
				Entity *entity,
				Entity__MakeMessage *creation_message
			);
		void
			ReplicantEntityCreation(
				Entity *entity,
				Entity__MakeMessage *creation_message
			);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Private interest origin management
	//
	private:
		void
			AddInterestingEntityToInterestOrigins(Entity *entity);
		void
			RemoveUninterestingEntityFromInterestOrigins(Entity *entity);
		void
			AddInterestingEntitiesToInterestOrigin(
				InterestOrigin *interest_origin
			);
		void
			RemoveUninterestingEntitiesFromInterestOrigin(
				InterestOrigin *interest_origin
			);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Private data
	//
	private:
		InterestLatticeManager
			interestLatticeManager;
		SChainOf<InterestOrigin*>
			interestOriginSocket;
		InterestArena
			*interestArena;

		static unsigned char
			messageBuildBuffer[INTERESTMANAGER_MESSAGE_BUFFER_SIZE];
	};

	//~~~~~~~~~~~~~ InterestManager__EntitySubscribeToUpdatesMessage ~~~~~~~~~~~

	class InterestManager__EntitySubscribeToUpdatesMessage:
		public NetworkClient::Message
	{
	public:
		InterestManager__EntitySubscribeToUpdatesMessage();
	};

	//~~~~~~~~~~~ InterestManager__EntityBroadcastToReplicantsMessage ~~~~~~~~~~

	class InterestManager__EntityBroadcastToReplicantsMessage:
		public NetworkClient::Message
	{
	public:
		InterestManager__EntityBroadcastToReplicantsMessage(
			size_t message_length
		);
	};

	//~~~~~~~~~~~~~ InterestManager__EntityNewInterestZoneMessage ~~~~~~~~~~~~~~

	class InterestManager__EntityNewInterestZoneMessage:
		public NetworkClient::Message
	{
	public:
		InterestManager__EntityNewInterestZoneMessage(
			const EntityID &entity_ID,
			InterestZoneID interest_zone_ID
		);

		EntityID
			entityID;
		InterestZoneID
			interestZoneID;
		//
		// HACK - a way is needed to get from the entity the information
		// required for another host to create the replicant
		//
	};

	//~~~~~~~~~~~~~ InterestManager__HostInterestArenaChangedMessage ~~~~~~~~~~~

	class InterestManager__HostInterestArenaChangedMessage:
		public NetworkClient::Message
	{
	public:
		InterestManager__HostInterestArenaChangedMessage();
	};

	//~~~~~~~~~~~~~~~~~ InterestManager__InterestZoneDeltaMessage ~~~~~~~~~~~~~~

	class InterestManager__InterestZoneDeltaMessage:
		public NetworkClient::Message
	{
	public:
		InterestManager__InterestZoneDeltaMessage();
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~ InterestManager inlines ~~~~~~~~~~~~~~~~~~~~~~~~~

	inline InterestLatticeManager*
		InterestManager::GetInterestLatticeManager()
	{
		return &interestLatticeManager;
	}

	inline InterestZone*
		InterestManager::GetInterestZone(InterestZoneID interestZoneID)
	{
		Check(&interestLatticeManager);
		return interestLatticeManager.GetInterestZone(interestZoneID);
	}

#endif

