/******************************************************************
  
  Module:  aiblackboard.h
  
  Author: Borut Pfeifer
  
  Description: Shared communication btwn agents

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

#ifndef AIBLACKBOARD_H
#define AIBLACKBOARD_H

#include <vector>
#include "../gameobj.h"


#define AIBLACKBOARD_CLASSID                      (SyPropClassID)(0xFFFFDEAD)
#define AIBLACKBOARD_RECORD_CLASSID               (SyPropClassID)(0xFFFFDEAE)

class cLevelObject;

class cAIBlackboard : public SyPropObject
{
public:

  //
  // List of entry types that each agent can store and know about
  //
  enum RecordType
  {
    BBR_INVALID = -1,
    BBR_ATTACKING_MELEE,
    BBR_ATTACKING_RANGED,
    BBR_FLANK_REQUEST,
    BBR_FLANK_PARTNER,
    BBR_RANGEDATTACK_LINE,
    BBR_DEFENDING,
    BBR_STUNNING,
    BBR_NEGATIVE_AREAEFFECT,
    BBR_POSITIVE_AREAEFFECT,
    BBR_MELEE_CIRCLE,

    // add before this
    BBR_MAX_TYPES
  };

  //
  // Record entry data structure, one for each element on the blackboard
  //
  class Record : public SyPropObject
  {
    public:
      Record();

      static int             InitPropClass();  
      static SyPropObject*   Creator();

      RecordType mType;
      tGameObjectID mSourceID;
      tGameObjectID mTargetID;
      unsigned int mData;
      SyVect3 mLocation;
      uint64 mCreatedTimestamp;
  };

  cAIBlackboard();
  ~cAIBlackboard();

  // Property Class Support 
  static int                         InitPropClass();  
  static SyPropObject*               Creator();

  void Init(cLevelObject* pLevelObj);

  //
  // Core interface to AI
  //
  int CountRecords(RecordType type,
                   tGameObjectID sourceID = ID_NONE,
                   tGameObjectID targetID = ID_NONE);

  bool GetFirstRecord(RecordType type,
                      tGameObjectID sourceID,
                      tGameObjectID targetID,
                      Record& rec);

  bool GetNextRecord(Record& rec);

  void AddRecord(RecordType type,
                 tGameObjectID sourceID,
                 tGameObjectID targetID = ID_NONE,
                 unsigned int data = 0,
                 const SyVect3& location = SyVect3(0.0f, 0.0f, 0.0f));

  void RemoveRecords(RecordType type,
                     tGameObjectID sourceID = ID_NONE,
                     tGameObjectID targetID = ID_NONE);


  // Singleton accessor
  static cAIBlackboard* Get(); 

  // Handle networking messages
  void NetworkReceiveBroadcast(const char *state, int maxlen);
  void NetworkReceiveMessage(const char *state, int maxlen);

  void SetRemote(bool bRemote);
  bool IsRemote();

protected:
  typedef SyVector<Record*> RecordVector;

  void AddRecordLocal(RecordType type, tGameObjectID sourceID, tGameObjectID targetID, unsigned int data, const SyVect3& location);
  void SendAddRecord(RecordType type, tGameObjectID sourceID, tGameObjectID targetID, unsigned int data, const SyVect3& location);
  void RemoveRecordsLocal(RecordType type, tGameObjectID sourceID, tGameObjectID targetID);
  void SendRemoveRecords(RecordType type, tGameObjectID sourceID, tGameObjectID targetID);

  static cAIBlackboard* smpInstance;

  RecordVector mRecords;
  RecordType mSearchRecordType;
  tGameObjectID mSearchSourceID;
  tGameObjectID mSearchTargetID;
  int mSearchIndex;
  cLevelObject* mpOwner;

  bool mbRemote;
};

inline cAIBlackboard* cAIBlackboard::Get()
{
  return smpInstance;
}


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

#endif
