#ifndef _RUWORLD_ENTITYSYSTEM_H_
#define _RUWORLD_ENTITYSYSTEM_H_

#include "../../Core/DataStore/RuDataStore_Base.h"
#include "../../Scene/Terrain/RuWorld_Base.h"

#pragma unmanaged

// ************************************************************************************************************************************************************

namespace RuWorld
{
	typedef boost::function<CRuArrayList<CRuGUID> & ()> EntityEnumerator;		// Parameters: (enumeratedGUIDListOut)
}

// ************************************************************************************************************************************************************

class CRuWorld_ObjectContainer : public IRuObject
{
	ruRTTI_DECLARE
	ruHEAP_DECLARE
	ruCLASSGUID_DECLARE

protected:
	// Data store
	CRuDataStore_Base*						m_dataStore;							//!< Data store
	INT32									m_tableHandle_Object;					//!< Handle to object table

	// Entity descriptor cache
	CRuLRUQueue<CRuGUID, IRuObject *>*		m_objectQueue;							//!< LRU queue of entity descriptors/objects
	CRuLRUQueue<CRuGUID, CRuEntity *>*		m_instanceQueue;						//!< LRU queue of instanced entities
	CRuKeyHash<CRuGUID>*					m_missingObjectHash;					//!< Hash of missing objects

	// Update list
	CRuArrayList<IRuObject *>				m_changedObjectList;					//!< List of changed objects
	CRuArrayList<CRuGUID>					m_deletedObjectList;					//!< List of deleted object GUIDs

public:
											CRuWorld_ObjectContainer();
	virtual									~CRuWorld_ObjectContainer();

	// Data source management
	BOOL									Attach(CRuDataStore_Base *dataStore);
	BOOL									SaveChanges();
	BOOL									CopyTo(CRuDataStore_Base *targetDataStore);

	// Object management
	BOOL									InsertObject(IRuObject *object);
	BOOL									DeleteObject(const CRuGUID &guid);
	BOOL									MarkObjectForUpdate(const CRuGUID &guid);
	IRuObject*								GetObject(const CRuGUID &guid);

	// CRuWorld_EntityDescriptor-specific stuff
	CRuWorld_EntityDescriptor*				GetEntityDescriptor(const CRuGUID &guid);
	CRuEntity*								GetEntityInstance(const CRuGUID &guid);

	// Queue management
	BOOL									ClearObjectQueue();
	BOOL									ClearInstanceQueue();

protected:
	IRuObject*								GetObjectFromChangeList(const CRuGUID &guid);

	BOOL									ClearObjectQueueCallback(const void *key, void *data);
	BOOL									ClearInstanceQueueCallback(const void *key, void *data);
};

// ************************************************************************************************************************************************************

class CRuWorld_ObjectManager : public CRuEntity_Container_Impl
{
	ruRTTI_DECLARE
	ruHEAP_DECLARE
	ruCLASSGUID_DECLARE

protected:
	CRuWorld_ObjectContainer*				m_objectContainer;					//!< Entity container
	RuWorld::EntityEnumerator				m_enumerator;						//!< Function used for entity GUID enumeration

	REAL									m_enumerationMarginSize;			//!< Size of margin to add to enumeration bounds
	CRuAABB									m_enumerationBounds;				//!< Current enumeration bounds including margin

	CRuKeyHash<CRuGUID>*					m_enumerationHash;					//!< Temporary hash for storing entity descriptor GUIDs

	BOOL									m_enableTriggerDisplay;

public:
											CRuWorld_ObjectManager();
	virtual									~CRuWorld_ObjectManager();

	// Container management
	BOOL									Attach(CRuWorld_ObjectContainer *container);
	BOOL									SetEnumerator(RuWorld::EntityEnumerator enumerator);
	BOOL									ClearEnumerationCache();

	BOOL									EnableTriggerDisplay(BOOL enable);

	BOOL									UpdateEnumeration(const CRuAABB &enumerationBounds);
	virtual BOOL							Update(REAL elapsedTime);
};

// ************************************************************************************************************************************************************

#pragma managed

#endif
