#ifndef RTI_RTI1516HandleFactory_h
#define RTI_RTI1516HandleFactory_h

#include <set>
#include <map>
#include <vector>
#include <list>
#include "certi.hh"
#include "GAV.hh"
#include <RTI/Typedefs.h>
#include "RTI1516HandleImplementation.h"
#include "M_Classes.hh"


template<class I>
struct certi_cast
{
    template<class R>
    const I& operator()(const R& imp)
    {
        try {
            return dynamic_cast<const I&>(imp);
        }
        catch (...)
        {
            throw rti1516::RTIinternalError(L"Incompatible object on input.");
        }
    }

    template<class R>
    I& operator()(R& imp)
    {
        try {
            return dynamic_cast<I&>(imp);
        }
        catch (...)
        {
            throw rti1516::RTIinternalError(L"Incompatible object on input.");
        }
    }
};

#define DEFINE_HANDLE_FRIEND_CLASS(HandleKind)                  \
																\
/* Forward declaration for the RTI-internal class            */ \
/* used to implement a specific kind of handle               */ \
class HandleKind;											    \
class HandleKind##Implementation;                               \
																\
/* Each handle class generated by this macro provides the    */ \
/* following interface                                       */ \
class RTI_EXPORT HandleKind##Friend                                        \
{                                                               \
public:                                                         \
   static HandleKind createRTI1516Handle(const certi::Handle & certiHandle);                   \
   static HandleKind createRTI1516Handle(const rti1516::VariableLengthData & encodedValue);    \
   static certi::Handle toCertiHandle(const HandleKind & rti1516Handle);				       \
																\
private:                                                        \
   HandleKind##Friend();                                        \
   ~HandleKind##Friend();                                       \
																\
};                                                              \

namespace rti1516
{

	// All of the RTI API's HandleFriend classes are defined 
	// by invoking the macro above.
	DEFINE_HANDLE_FRIEND_CLASS(FederateHandle)
	DEFINE_HANDLE_FRIEND_CLASS(ObjectClassHandle)
	DEFINE_HANDLE_FRIEND_CLASS(InteractionClassHandle)
	DEFINE_HANDLE_FRIEND_CLASS(ObjectInstanceHandle)
	DEFINE_HANDLE_FRIEND_CLASS(AttributeHandle)
	DEFINE_HANDLE_FRIEND_CLASS(ParameterHandle)
	DEFINE_HANDLE_FRIEND_CLASS(DimensionHandle)
	//DEFINE_HANDLE_FRIEND_CLASS(MessageRetractionHandle)
	DEFINE_HANDLE_FRIEND_CLASS(RegionHandle)
	  
	class MessageRetractionHandleFriend {
	public: 
	   static MessageRetractionHandle createRTI1516Handle(const certi::Handle & certiHandle, uint64_t serialNr);   
	   static MessageRetractionHandle createRTI1516Handle(const rti1516::VariableLengthData & encodedValue);  
	   static certi::EventRetraction createEventRetraction(const rti1516::MessageRetractionHandle & messageRetractionHandle);
	private:                                                        															
	   MessageRetractionHandleFriend();                                        
	   ~MessageRetractionHandleFriend();                                       
	};	

}

#endif // RTI_RTI1516HandleFactory_h
