/******************************************************************
  
  Module:  Registry.h
  
  Author: Sean Craig
  
  Description:  Registry for game objects

  
  Copyright 2005 Sony Online Entertainment.  All rights reserved.
  
*******************************************************************/

#ifndef REGISTRY_H
#define REGISTRY_H

//-------------------------------------------------------- Includes

#include "gameobj.h"
//#include "levelobj.h"
#include "SyMap.h"
#include "SyString.h"
#include "SySceneTypes.h"
#include "SyEmbeddedHashList.h"

//-------------------------------------------------------- Typedefs
//---------------------------------------------- Class Declarations
class Titan;
class cLevelObject;
class SyObjFile;
class TitanSave;

static const int GAMEOBJECTREGISTRY_CLASSID  =  0xFFFFA001;

class cGameObjectRegistry : public SyPropObject
{
public:
                    cGameObjectRegistry();
                    ~cGameObjectRegistry();

  void              Clear();
  void              ClearNonplayer(); // clears all but players (used for level transitions)

                    /* Property Class Support */
  static int           InitPropClass();
  static SyPropObject* Creator();  
  
  void              Init(Titan *parent); 
  void              LoadLevelXML(const char *xml_filename);  
  void              LoadLevelBinary(const char *filename);   
  void              SaveLevelBinary(const char *filename);
  void              NudgeProps();

  void              TransitionLevel(const char *filename);   

  void              InitObject(tGameObjectID id,bool ownerLifetime);
  void              Update(float time); 
  void              UpdateJustProps(float time);  // for use with havok stabilization

  void              Prerender();
  
  tGameObjectID     Create(cGameObject::tObjectType newtype); // creates and registers objects
  bool              Name(cGameObject *obj,const char *name);  // assign a name to an object
  int               Delete(tGameObjectID);
  cGameObject *     Fetch(tGameObjectID id);
  cGameObject *     Fetch(const char *name);

  cGameObject *     FetchByActorHandle(SyActorHandle handle); 

  tGameObjectID     NetworkCreate(cGameObject::tObjectType newtype,tGameObjectID id,const char *state,int statelen); // creates and registers objects
  void              NetworkSetState(tGameObjectID id,const char *state,int statelen); // Resets an object to a particular state
  unsigned int      NetworkGetState(tGameObjectID id,char *state, int maxlen);
  void              NetworkDelete(tGameObjectID id);
  unsigned int      NetworkReceiveBroadcast(tGameObjectID id,const char *state, int maxlen);
  unsigned int      NetworkReceiveMessage(tGameObjectID id,const char *state, int maxlen);
  unsigned int      NetworkTakeOwnership(tGameObjectID id);
  void              NetworkRequestOwnership(tGameObjectID id, int requestingPeerId);

  int               GetNumRemotePlayers();
  int               GetNumGameObjects() { return mIDHashTable.Count(); }

  // for iterating over all world objects
  cGameObject *     Begin(){return mIDHashTable.First();};
  cGameObject *     Next(cGameObject *obj){return mIDHashTable.Next(obj);};

  // for iterating over objects of a particular type
  cGameObject *     BeginType(cGameObject::tObjectType type){return mTypeLists[type]->First();};
  cGameObject *     NextType(cGameObject *obj){return mTypeLists[obj->GetType()]->Next(obj);};

  Titan *           GetTitan(){return mpTitan;};
  cLevelObject*     GetLevelObject(){return mpLevelObject;};

  int               SaveGameGetCount() { return mNumSaveGames; }
  bool              SaveGameGetInfo(int index, TitanSave* pInfo);
  bool              SaveGameLoad(int index);
  bool              SaveGameOverwrite(int index, const SyString& desc);
  bool              SaveGameCreate(const SyString& desc);
  bool              SaveGameLoadLast();
  bool              SaveGameOverwriteLast();


  cGameObject *     BeginMin(){return mXMin.First();};
  cGameObject *     NextMin(cGameObject *obj){return mXMin.Next(obj);};
  cGameObject *     PrevMin(cGameObject *obj){return mXMin.Prev(obj);};
  cGameObject *     BeginMax(){return mXMax.First();};
  cGameObject *     NextMax(cGameObject *obj){return mXMax.Next(obj);};
  cGameObject *     PrevMax(cGameObject *obj){return mXMax.Prev(obj);};
  cGameObject *     BeginOpen(){return mOpen.First();};
  cGameObject *     NextOpen(cGameObject *obj){return mOpen.Next(obj);};
  void              AddOpen(cGameObject *obj){mOpen.InsertTail(obj);};
  void              RemoveOpen(cGameObject *obj){mOpen.Remove(obj);};
  void              ClearOpen(){mOpen.RemoveAll();};

  void              ReinsertAfterMin(cGameObject *before,cGameObject *after);
  void              ReinsertAfterMax(cGameObject *before,cGameObject *after);

 protected:
  void              CheckForDelete(); // checks all objects to see if they should be deleted...
  bool              Add(cGameObject *obj);

  void              ReadSaveGames();
  bool              WriteSaveGameData(SyObjFile& file);

  Titan *           mpTitan;

  // This could be replaced with a SyVector (will require a .lvl file format change)
  // It's only still in here for PropObj support

  SyMap<tGameObjectID,cGameObject *>  mObjects; 
  cLevelObject *    mpLevelObject;

  enum { REGISTRY_HASH_SIZE = 1000 };
  SyEmbeddedHashList<cGameObject, &cGameObject::mIDListLink, &cGameObject::mIDHashLink, REGISTRY_HASH_SIZE>  mIDHashTable;
  SyEmbeddedHash<cGameObject, &cGameObject::mNameLink, REGISTRY_HASH_SIZE> mNameHashTable;  
  SyEmbeddedList<cGameObject, &cGameObject::mTypeLink> *                   mTypeLists[cGameObject::NUM_OBJ_TYPES];

  SyEmbeddedList<cGameObject, &cGameObject::mMinLink>                    mXMin; // used for faster collision detection
  SyEmbeddedList<cGameObject, &cGameObject::mMaxLink>                    mXMax; // used for faster collision detection
  SyEmbeddedList<cGameObject, &cGameObject::mOpenLink>                   mOpen; // used for faster collision detection

  int mNumSaveGames;
  int mLastSaveGameIndex;
};


//------------------------------------------- Function Declarations
//--------------------------------------------------------- Globals
void RegPropClasses_Registry();


//------------------------------------------------ Inline Functions

#endif
