#pragma once

#include "AftrConfig.h"
#ifdef AFTR_CONFIG_USE_BOOST

#include <map>
#include "NetMessengerStreamBuffer.h"
#include "NetMsg_callback_decl.h"

namespace Aftr
{
   class NetMsg;
   typedef NetMsg* (*FuncPtrNetMsgFromStream) ( NetMessengerStreamBuffer& );

   class ManagerSerializableNetMsgMap
   {
   public:
      static void shutdownManager();
      static void registerNetMsgType( const std::string& netMsgStr, FuncPtrNetMsgFromStream funcPtrNetMsgFromStream );
      static NetMsg* createInstance( unsigned int netMsgID, NetMessengerStreamBuffer& is );
      static bool isValidHeader( unsigned int netMsgID );
      
      /// Returns the corresponding unsigned int that is sent across the wire to identify
      /// NetMessage of type className. Returns 0 if an invalid className is passed in.
      /// The first valid ID begins with 1.
      static unsigned int getNetMsgID( const std::string& className );

      /// When the user inovkes GLView::subscribe_NetMsg_to_callback( callback_on_NetMsgT_arrived<NetMsgT> call_on_Arrived )
      static bool register_NetMsg_to_user_defined_callback( callback_NetMsgT_erased func );

      //Returns true iff NetMsgID has a user-registered callback that can be invoked. Otherwise, the default
      //this method will return false. Typically, this function is called first, and if it returns true, then
      //the virtual onMessageArrived() is *never* invoked (since we just let the user-specified callback occur).
      //If this function returns false, then somewhere later, it is usually expected that the 
      //virtual onMessageArrived() method will be called as the default callback.
      //IF THIS METHOD returns TRUE -- it has FULLY TAKEN OWNSHIP of the NetMsg* and this callchain should no
      //longer manage any part of it (in otherwords NetMsg* msg has now been transferred into a std::unique_ptr).
      static bool invoke_user_defined_callback_transferring_ownership( NetMsg* msg );

   protected:
      static void init();
      static unsigned int getStringHash( const std::string& str );
      static bool hashCollisionExists( const std::string& newClassName );
      static std::map< unsigned int, FuncPtrNetMsgFromStream >* idToFuncMap; ///< Maps NetMsgID to create method
      static std::map< std::string, unsigned int >* stringToNameMap; ///< Maps string of NetMsgID class name to its NetMsgID
   };

} //namespace Aftr

#endif
