///////////////////////////////////////////////////////////////////////////////
/// @file deWorld.hpp
///
/// @brief Destiny "World" storage
///
/// @author Assassin
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Dec 2001
/// @author Assassin
/// @remarks Creation
///
/// @date Feb 2002
/// @author Assassin
/// @remarks Rendering functionality moved to deRender
///
/// @date Sep 2002
/// @author Assassin
/// @remarks Tear-down and re-write
///
///////////////////////////////////////////////////////////////////////////////

#ifndef DEWORLD_HPP
#define DEWORLD_HPP

#include "deGlobalTypes.hpp"
#include "deArray.hpp"
#include "deResource.hpp"

#if defined(DEWORLD_DLL_EXPORTS) || defined(DESTINY3D_EXPORT_ALL)
#	define DEWORLD_API extern "C" DEDLL_EXPORT
#elif defined(DESTINY3D_STATIC_LINK)
#	define DEWORLD_API extern "C"
#else
#	define DEWORLD_API extern "C" DEDLL_IMPORT
#endif

#ifdef USING_DESTINY3D
#ifdef _DEBUG
#	ifdef DESTINY3D_STATIC_LINK
#		pragma comment(lib, "deWorld_sd")
#	else
#		pragma comment(lib, "deWorldd")
#	endif //DESTINY3D_STATIC_LINK
#else
#	ifdef DESTINY3D_STATIC_LINK
#		pragma comment(lib, "deWorld_s")
#	else
#		pragma comment(lib, "deWorld")
#	endif //DESTINY3D_STATIC_LINK
#endif //_DEBUG
#endif //USING_DESTINY3D

class IdeFile;
class IdeWorld;
class IdeWorldManager;
class IdeWorldObject;

/// Exported function for retrieving a pointer to the deWorldManager singleton
	DEWORLD_API IdeWorldManager*	IdeWorld_GetManager();
	DEWORLD_API void				IdeWorld_ShutDown();

typedef IdeWorldManager* (*fIdeWorld_GetManager)();
typedef IdeWorldObject* (*IdeWorldObject_Creator)();

/// Manager for various deWorld duties
//class IdeWorldManager
DE3D_INTERFACE_(IdeWorldManager)
{
protected:
	~IdeWorldManager() {}
public:
	/// create a world that can then be used to store data
	virtual deWorldID CreateWorld() = 0;
	/// retrieve a created world
	virtual IdeWorld* GetWorld(deWorldID ID) = 0;
	/// retrieve a world object without need for retrieving the world pointer
	virtual IdeWorldObject*	GetWorldObject(deWorldID WID, deObjectID OID) = 0;
	/// get the deResource interface ID for deWorld
	virtual long GetRscInterfaceID() = 0;
	/// obtain a unique ID to use when using classes derived from deWorldObject
	virtual long GetUniqueWOInterfaceID() = 0;
	/// register a WorldObject class, which can then be loaded by string identifier
	virtual deBoolean RegisterWOClass(const char* ClassName, IdeWorldObject_Creator creator) = 0;
};

/// IdeWorld is the basic interface to the deWorld storage class
//class IdeWorld : virtual public IdeResourceBase
DE3D_INTERFACE(IdeWorld, IdeResourceBase)
{
protected:
	virtual ~IdeWorld(void) {}
public:
	/// Get the ID number of this world
	virtual deWorldID	GetWorldID() = 0;
	/// Used by descendants of IdeWorldObject so that they can store a "local" world ID 
	/// which is serializable, using a translation layer. Reverses GetLocalIDFromLoadedWorld output
	virtual deWorldID	GetWorldIDUsingLocalID(deWorldID LocalID, deBoolean ForceLoad = deFALSE) = 0;
	/// translates the ID of a currently loaded deWorld into a "local" world ID that 
	/// world objects can serialize safely. 
	virtual deWorldID	GetLocalIDFromLoadedWorld(deWorldID WorldID) = 0;
	/// Get the interface to an object based on its ID
	virtual IdeWorldObject*	GetWorldObject(deObjectID ObjectID) = 0;

	/// Write the world to an open file
	virtual deBoolean	Serialize(IdeFile* File) = 0;
	/// Read the world from an open file
	virtual deBoolean	DeSerialize(IdeFile* File) = 0;

	/// Call repeatedly to retrieve the typenames of all the stored items
	/// @return pointer to character array containing name of a type
	/// @param PrevEntry a void pointer that is modified inside the function. Set to NULL for the first call.
	virtual const char*	GetNextObjectTypeName(void* &PrevEntry) = 0;
	/// Call repeatedly to retrieve the stored objects
	/// @return the ID of an object stored in this world with the type name specified
	/// @param TypeName a string indicating the typename of an object. Use return value of GetNextObjectTypeName.
	/// @param PrevEntry a void pointer that is modified inside the function. Set to NULL for the first call.
	virtual deObjectID	GetNextObjectOfType(const char* TypeName, void* &PrevEntry) = 0;

	// following methods for internal use only
	// obtain a unique item ID to use within this world
	virtual deObjectID	AddWorldObject(IdeWorldObject * Object) = 0;
	virtual deBoolean	AddWorldObjectWithID(IdeWorldObject * Object) = 0;
	virtual deBoolean	RemoveWorldObject(deObjectID ObjectID) = 0;
};

/// IdeWorldObject is the abstract base for a deWorld to talk to its objects
//class IdeWorldObject : virtual public IdeRefCountBase
DE3D_INTERFACE(IdeWorldObject, IdeRefCountBase)
{
protected:
	virtual ~IdeWorldObject() {}
public:
	/// request a related interface, identified with an ID originally returned from 
	/// IdeWorldManager::GetUniqueWOInterfaceID
	virtual void*		GetWOInterface(long interface_id) = 0;
	/// retrieve the specific type name of the object
	virtual const char*	GetWOTypeName() = 0;
	
	/// Retrieve the object's world-unique object ID
	virtual deObjectID	GetObjectID() = 0;
	/// Retrieve the object's runtime-unique World ID
	virtual deWorldID	GetWorldID() = 0;

	/// Set the object's world ID to a specified World ID.
	/// @param WorldID 0 or a valid ID for a currently loaded deWorld
	/// @param ObjectID Reserved use - Use 0 (default)
	virtual deBoolean	SetWorldID(deWorldID WorldID, deObjectID ObjectID = 0) = 0;

	/// Set a private data member for this object, along with its size in bytes.
	/// This data is serialized, so don't store any pointer data.
	/// The data is copied into an internally-allocated area, so you can feed local variables in.
	/// Calling with 'pData = NULL' will cause it to destroy the data.
	virtual deBoolean	SetPrivateData(void* pData, long Size) = 0;
	/// Retrieve the private data member for this object, along with its size in bytes.
	virtual void*		GetPrivateData(long & pSize) = 0;

	/// Serialize the object into an open IdeFile - used by deWorld internally
	virtual deBoolean	Serialize(IdeFile* File) = 0;
	/// De-Serialize the object from an open IdeFile - used by deWorld internally
	virtual deBoolean	DeSerialize(IdeFile* File, long DataLength) = 0;
	/// Call after all objects in a world have been loaded, to allow pointers to be correctly
	/// resolved from World and Object ID's
	virtual deBoolean	DeSerializeLoad() = 0;
};

#endif
