/******************************************************************
  
  Module:  service.h
  
  Author: Sean Craig
  
  Description:  This is my attempt to engineer a system for doing 
  things in a way which matches the PS3 hardware more closely than 
  traditional object oriented architecture.

  A service is a small chunk of code which runs on a data set.  

  The idea is that we would have an animated character physics service, 
  a dynamic physics service, a projectle physics service, etc.
  Each service would keep a list of objects it acts on, along with
  the data it needs.  Then we can ship off the expensive services
  to a SPU.

  This is the Visitor pattern.

  The immediate client for this type of system is the 
  MotionController_Service which moves objects along curves according
  to the scripting system.

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

#ifndef SERVICE_H
#define SERVICE_H

//-------------------------------------------------------- Includes
#include "nameid.h"
#include "SyEmbeddedHashList.h"
//-------------------------------------------------------- Typedefs
//---------------------------------------------- Class Declarations

class Titan;

class cService 
{
public:

  cService(){};
  virtual ~cService(){};

  virtual void Init(Titan *titan){mpTitan = titan;};  // once on startup 
  virtual void Reset(){}; // once on level change


  virtual void Perform(float time)=0;  // performs the service

  virtual  tGameID GetID() const =0;

  SyEmbeddedHashLink<cService> mHashLink;   
  SyEmbeddedListLink<cService> mListLink;  



protected:
  Titan                      *mpTitan;

  // cServices must have a static member mNameID.
  // static cNameID                      mNameID;

  // initialize it in your header by
  // cNameID cService::mNameID("SERVICE_NAME");

};


// TODO: Priority queue? Synchronization?  Service dependencies?
class cServiceScheduler
{
public:

  cServiceScheduler();
  ~cServiceScheduler();

  void Init(Titan *titan);

  void Reset(); // resets services; don't need to re-add services after this call.

  void Perform(float time);

  void AddService(cService *service);

  cService *Fetch(tGameID id);


  // ex:
  // myService *a = myScheduler->GetService<myService>();
  template<class T> 
  T GetService()
  {
    return static_cast<T>(Fetch((static_cast<T>(0))->mNameID.GetID()));
  }

protected:
  Titan               *mpTitan;
  SyEmbeddedHashList<cService,&cService::mListLink, &cService::mHashLink,127> mServices;   
  
};


//------------------------------------------- Function Declarations
//--------------------------------------------------------- Globals
//------------------------------------------------ Inline Functions

#endif
