#ifndef  DIAMETERCODETS_H
#define  DIAMETERCODETS_H

#include <t3devlib/t3devlib.h>
#include <t3devlib/generator.h>

namespace t3devlib {
namespace gen {

//type UInt32 AVP_Code (1..c_uInt32Max);
T3DEVLIB_INTEGER_DEFINITION(LibDiameter_TypesAndValues, AVP_Code, Unsigned, 32);

//type UInt24 AVP_Length;
T3DEVLIB_INTEGER_DEFINITION(LibDiameter_TypesAndValues, AVP_Length, Unsigned, 24);

//type integer AVP_Vendor_ID;
T3DEVLIB_INTEGER_DEFINITION(LibDiameter_TypesAndValues, AVP_Vendor_ID, Unsigned, 32);//in spec, 4 bytes

//TODO: although defined as Uint64 only encoded as 4 bytes
//type UInt64 Time;
//T3DEVLIB_INTEGER_DEFINITION(LibDiameter_TypesAndValues, Time, Unsigned, 64);
T3DEVLIB_INTEGER_DEFINITION(LibDiameter_TypesAndValues, Time, Unsigned, 32);

//type UInt8 Digest_Ty_Type;
T3DEVLIB_INTEGER_DEFINITION(LibDiameter_TypesAndValues, Digest_Ty_Type, Unsigned, 8);


//type charstring Diameter_Identity; 
T3DEVLIB_BASIC_DEFINITION (LibDiameter_TypesAndValues, Diameter_Identity, Charstring);

//TODO: how are universal charstrings handled?
//type universal charstring UTF8String;
T3DEVLIB_BASIC_DEFINITION (LibDiameter_TypesAndValues, UTF8String, Charstring);

//typedef float FLOAT32; cannot be cast to Variable*
	class FLOAT32 : public ::t3devlib::PrimitiveType
	{
	public:
	/** Standard constructor */
		FLOAT32 ();
		virtual ~FLOAT32();
		
		int GetLength() const;
		::t3devlib::Variable::BaseType GetBaseType() const;

		/** Get the current value of the integer */
		float GetValue() const;

		/** %Set a new value */
		void SetValue(float v);

		/** %Set a new value */
		void SetValue(const FLOAT32& v);

		const unsigned char* GetValueBin() const;

		void Decode (Buffer& buffer) throw (DecodeError);
		void Encode (Buffer& buffer) throw (EncodeError);

		void Dump (std::ostream& out, int indent=0) const;

		void DumpInline (std::ostream& out) const;


	protected:
		void SetValueBinNoOffset (const unsigned char* buff, int bit_length=-1);
		/** \internal buffer for returning binary values */
		mutable std::string msBinBuff;
		
	private:
		/** \internal Internal value of the integer */
		float mValue;
	};


	class FLOAT64 : public ::t3devlib::PrimitiveType
	{
	public:
	/** Standard constructor */
		FLOAT64 ();
		virtual ~FLOAT64();
		
		int GetLength() const;
		
		::t3devlib::Variable::BaseType GetBaseType() const;

		/** Get the current value of the integer */
		double GetValue() const;

		/** %Set a new value */
		void SetValue(double v);

		/** %Set a new value */
		void SetValue(const FLOAT64& v);

		const unsigned char* GetValueBin() const;

		void Decode (Buffer& buffer) throw (DecodeError);
		void Encode (Buffer& buffer) throw (EncodeError);

		void Dump (std::ostream& out, int indent=0) const;

		void DumpInline (std::ostream& out) const;


	protected:
		void SetValueBinNoOffset (const unsigned char* buff, int bit_length=-1);
		
		/** \internal buffer for returning binary values */
		mutable std::string msBinBuff;
	
	private:
		/** \internal Internal value of the integer */
		double mValue;
	};

#define SIP_AOR_Type DiameterURI

//type record length (4) of UInt8  IPv4Addr;
//RECORDOF_COMMON_DEFINITIONS(LibDiameter_TypesAndValues, IPv4Addr);


	class Command_Code : public ::t3devlib::Enum
	{
	private:
		static const char* msKeywordEnumsAll[];
		static const char* msKeywordEnumsRequest[];
		static const char* msKeywordEnumsAnswer[];
		static const int msCommandCodeValues[];
		bool m_bIsRequest;
	public:	\
		
		Command_Code () : Enum (msKeywordEnumsAll)	{}
		
		const char* GetModuleName() const { return "LibDiameter_TypesAndValues"; }
		const char* GetTypeName() const   { return "Command_Code"; }
		
		void Encode (Buffer& buffer) throw (EncodeError);
		void Decode (Buffer& buffer) throw (DecodeError);
		void SetRequest(){m_bIsRequest = true;}
	};

//cannot contain -1 as enum id !!!!
#define AVP_ENUM_U32_DEFINITION(module, type)	\
	class type : public ::t3devlib::Enum	\
	{	\
		private:	\
			static const char* msKeywordEnums[];	\
			static const unsigned int msKeywordIds[];	\
	public:	\
		type () : Enum (msKeywordEnums)	{}	\
		\
		const char* GetModuleName() const { return #module; } \
		const char* GetTypeName() const   { return #type; } \
		\
		void Encode (Buffer& buffer) throw (EncodeError)	\
		{	\
			Unsigned value(32);	\
			const char * pStr = GetValueString();	\
			for(int i=0; strlen(msKeywordEnums[i]); i++)	\
			{	\
				if(!strcmp(msKeywordEnums[i], pStr))\
				{	\
					value.SetValue (msKeywordIds[i]);	\
					value.Encode(buffer);	\
					break;	\
				}	\
			}	\
		}	\
		void Decode (Buffer& buffer) throw (DecodeError)	\
		{	\
			Unsigned value(32);	\
			value.Decode(buffer);	\
			unsigned int nValue = value.GetValue();	\
			for(int i=0; strlen(msKeywordEnums[i]); i++)	\
			{	\
				if(msKeywordIds[i] == nValue)	\
				{	\
					SetValueString (msKeywordEnums[i]);	\
					break;	\
				}	\
			}	\
		}	\
	};

#define AVP_ENUM_S32_DEFINITION(module, type)	\
	class type : public ::t3devlib::Enum	\
	{	\
		private:	\
			static const char* msKeywordEnums[];	\
			static const int msKeywordIds[];	\
	public:	\
		type () : Enum (msKeywordEnums)	{}	\
		\
		const char* GetModuleName() const { return #module; } \
		const char* GetTypeName() const   { return #type; } \
		\
		void Encode (Buffer& buffer) throw (EncodeError)	\
		{	\
			Signed value(32);	\
			const char * pStr = GetValueString();	\
			for(int i=0; strlen(msKeywordEnums[i]); i++)	\
			{	\
				if(!strcmp(msKeywordEnums[i], pStr))\
				{	\
					value.SetValue (msKeywordIds[i]);	\
					value.Encode(buffer);	\
					break;	\
				}	\
			}	\
		}	\
		void Decode (Buffer& buffer) throw (DecodeError)	\
		{	\
			Signed value(32);	\
			value.Decode(buffer);	\
			int nValue = value.GetValue();	\
			for(int i=0; strlen(msKeywordEnums[i]); i++)	\
			{	\
				if(msKeywordIds[i] == nValue)	\
				{	\
					SetValueString (msKeywordEnums[i]);	\
					break;	\
				}	\
			}	\
		}	\
	};

#define AVP_ENUM_DEFINITION(module, type)	\
	class type : public ::t3devlib::Enum	\
	{	\
		private:	\
			static const char* msKeywordEnums[];	\
			static const char* msKeywordStrings[];	\
	public:	\
		type () : Enum (msKeywordEnums)	{}	\
		\
		const char* GetModuleName() const { return #module; } \
		const char* GetTypeName() const   { return #type; } \
		\
		void Encode (Buffer& buffer) throw (EncodeError);\
		void Decode (Buffer& buffer) throw (DecodeError);\
	};


AVP_ENUM_U32_DEFINITION(LibDiameter_TypesAndValues, Result_Code_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Re_Auth_Req_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Redirect_Host_Usage_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Acc_Record_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Acc_Realtime_Req_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Termination_Cause_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Disconnect_Cause_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Auth_Session_State_Type)

AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, SIP_User_Auth_Ty_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, SIP_Srv_Assgmt_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, SIP_Usr_Dat_Al_Av_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, SIP_Auth_Schm_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, SIP_Reason_Code_Type)

AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Data_Reference_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Subs_Req_Ty_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Request_Domain_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Current_Location_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Identity_Set_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Send_Data_Indication_Type)

AVP_ENUM_U32_DEFINITION(LibDiameter_TypesAndValues, Experimental_Result_Type)

AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, CC_Request_Ty_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Subscription_Id_Ty_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Requested_Action_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Tariff_Change_Usage_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Multiple_Serv_Indi_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, CC_Unit_Ty_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Final_Unit_Action_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Redirect_Address_Ty_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, User_Equipment_Info_Ty_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, CC_Session_Failover_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Check_Balance_Result_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Credit_Cont_Fail_Hand_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Direct_Debi_Fail_Hand_Type)


AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Abort_Cause_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Flow_Status_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Flow_Usage_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Specific_Action_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Media_Type_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Service_Info_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, SIP_Forking_Indication_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, AF_Signalling_Protocol_Type)

AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Reservation_Priority_Type)

AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, IP_CAN_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, RAT_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Bearer_Control_Mode)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Bearer_Operation)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Bearer_Usage)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Charging_Correlation_Indicator)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, CSG_Information_Reporting)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Event_Trigger)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Flow_Direction)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Metering_Method)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Network_Request_Support)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Offline)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Online)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Packet_Filter_Operation)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Packet_Filter_Usage)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Pre_emption_Capability)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Pre_emption_Vulnerability)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Reporting_Level)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, PCC_Rule_Status)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Session_Release_Cause)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, QoS_Class_Identifier)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, QoS_Negotiation)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, QoS_Upgrade)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Resource_Allocation_Notification)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Rule_Failure_Code)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Usage_Monitoring_Level)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Usage_Monitoring_Report)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Usage_Monitoring_Support)

AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, CSG_Access_Mode)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, CSG_Membership_Indication)

AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Trace_Depth)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Job_Type)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Report_Interval)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Report_Amount)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Logging_Interval)
AVP_ENUM_S32_DEFINITION(LibDiameter_TypesAndValues, Logging_Duration)

//TODO: I have no idea where this is used....???
AVP_ENUM_U32_DEFINITION(LibDiameter_TypesAndValues, ASP_type)


#define DEFINITIONS_CER_MSG() \
	private: \
		int m_nStartingPosition;

#define DEFINITIONS_CEA_MSG() \
	private: \
		int m_nStartingPosition;

#define DEFINITIONS_RAR_MSG() \
	private: \
		int m_nStartingPosition;


//class variable definitions
#define DEFINITIONS_AVP_Data() \
	public: \
		int m_nDataLength; \
		int m_nExpectedData;


#define DEFINITIONS_set_of_AVP_Type() \
	public: \
		int m_nRemainingDataLength; \
		int m_nStartingPosition;


#define DEFINITIONS_Sponsored_Connectivity_Data_AVP() \
	public: \
		int m_nStartingPosition;

//set type field counters
#define DEFINITIONS_CC_Money_AVP() \
	private:	\
		int m_nFieldIndex;


#define DEFINITIONS_Requested_Service_Unit_AVP() \
	private:	\
		int m_nFieldIndex;


#define DEFINITIONS_Granted_Service_Unit_AVP() \
	private:	\
		int m_nFieldIndex;

#define DEFINITIONS_Used_Service_Unit_AVP() \
	private:	\
		int m_nFieldIndex;
}} //namespaces

#endif

