///////////////////////////////////////////////////////////////////////////////
/// @file deWorld_priv.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_PRIV_HPP
#define DEWORLD_PRIV_HPP

#include "deWorld.hpp"
#include "deHash.hpp"
#include "deList.hpp"
#include "deString.hpp"
#include "deMath.hpp"
#include "deIDServer.hpp"
#include "deResource_Helper.hpp"

class deWorld;

class deWorldManager : public IdeWorldManager
{
private:
	deWorldManager();

public:
	~deWorldManager();
	friend IdeWorldManager* IdeWorld_GetManager();
	
	deWorldID	CreateWorld();
	IdeWorld*	GetWorld(deWorldID ID);
	IdeWorldObject*	GetWorldObject(deWorldID WID, deObjectID OID);
	long		GetRscInterfaceID();
	long		GetUniqueWOInterfaceID();
	deBoolean	RegisterWOClass(const char* ClassName, IdeWorldObject_Creator creator);
	
	deBoolean	Initialize();
	deBoolean	ShutDown();
	deBoolean	RemoveWorld(deWorldID WorldID);
	deWorldID	AddWorld(deWorld* pWorld);
	IdeWorldObject*	CreateWorldObject(const char* ClassName);
	
	static long		s_WorldRscInterfaceID;
private:
	long			m_LatestWOID;
	IdeIDServer*	m_WorldIDServer;
	deTHashString <IdeWorldObject_Creator> m_TypeHash;
};


class deWorld : public deResourceBase, public IdeWorld
{
public:
	deWorld();
	deWorld(const char* filename);
	~deWorld();
	IdeResourceBase * MakeCopy();
	void * GetRscInterface(long interface_id);
	
	deWorldID	GetWorldID();
	deWorldID	GetWorldIDUsingLocalID(deWorldID LocalID, deBoolean ForceLoad);
	deWorldID	GetLocalIDFromLoadedWorld(deWorldID WorldID);
	IdeWorldObject*	GetWorldObject(deObjectID ObjectID);
	deObjectID	AddWorldObject(IdeWorldObject * Object);
	deBoolean	AddWorldObjectWithID(IdeWorldObject * Object);
	deBoolean	RemoveWorldObject(deObjectID ObjectID);
	
	deBoolean	SetWorldID(deWorldID ID);
	
	const char*	GetNextObjectTypeName(void* &PrevEntry);
	deObjectID	GetNextObjectOfType(const char* TypeName, void* &PrevEntry);

	deBoolean	Serialize(IdeFile* File);
	deBoolean	DeSerialize(IdeFile* File);
	
	deBoolean	WriteHeader(IdeFile* File);
	deBoolean	CheckHeader(IdeFile* File);

	deBoolean	WriteObjectInfo(IdeFile* File, deObjectID ObjectID, char * TypeName);
	deBoolean	WriteObjectDataLength(IdeFile* File, long ObjectStartPos);
	deBoolean	ReadObjectInfo(IdeFile* File, deObjectID &ObjectID, char TypeNameBuffer[256], long &DataLength);

protected:
	deBoolean	RecordObjectWithTypeName(deObjectID ObjectID, const char* TypeName);
	deBoolean	LoadFromFile(IdeFile * file);
	friend IdeResourceBase * LoadWorldFile(const char * filename, IdeFile * worldfile, deBoolean isThreaded);
	friend __declspec(dllexport) deBoolean IdeWorld_Initialize();
	friend __declspec(dllexport) long IdeWorld_GetRscInterfaceID();

private:
	struct WorldRef_t
	{
		deWorldID		LocalID;
		deWorldID		CurrentID;
		deTransformInfo	Transform;
		char			FileName[256];
	};
	deWorldID	m_WorldID;
	deObjectID	m_LatestItemID;
	deBoolean	m_LockDown;
	IdeIDServer*m_ObjectIDServer;
	deTHashString < deTList<deObjectID> > m_ObjectListHash;
	deTList <deString> m_ObjectTypesUsed;
#pragma note (perhaps use a multi-hash instead of an array)
	deTArray <WorldRef_t> m_ReferencedWorlds;
};

#endif