/** @file iencoder.h
*	virtual interface templates for EABaseType encoders/decoders
*	@author Chris Burns (cburns@ea.com)
*
*	EABaseTypes
*	(c) 2011 Electronic Arts Inc.
*/

#ifndef EABASETYPES_IENCODER_H_
#define EABASETYPES_IENCODER_H_

// for size_t
#include "EABase/eabase.h"

#include "EABaseTypes/basetypefloat.h"
#include "EABaseTypes/autoref.h"

namespace EA
{
	namespace Types
	{
		EABASETYPES_FORWARD_DECLARATION(class, Function)
		EABASETYPES_FORWARD_DECLARATION(class, UserData)
		
		/*! @class IEncoder iencoder.h	"EABaseTypes/iencoder.h"
		*	@brief IEncoder virtual interface
		*/
		class IEncoder
		{
		public:

			virtual ~IEncoder() {}

			/*!
			*	Called to reset the encoder
			*/
			virtual void Reset() = 0;

			/*!
			*	Called to indicate that we're beginning an Array
			*/
			virtual void BeginArray() = 0;

			/*!
			*	Called to indicate that we're ending an Array
			*/
			virtual void EndArray() = 0;

			/*!
			*	Called to indicate that we're beginning an Array element
			*	@param	index	The index of the element
			*	@note	This should always be called in order (0, 1, 2, 3, 4...)
			*/
			virtual void BeginArrayValue(size_t index) = 0;

			/*!
			*	Called to indicate that we're ending an Array element
			*	@param	index	The index of the element
			*/
			virtual void EndArrayValue(size_t index) = 0;

			/*!
			*	Called to indicate that we're beginning an Object
			*/
			virtual void BeginObject() = 0;

			/*!
			*	Called to indicate that we're ending an Object
			*/
			virtual void EndObject() = 0;

			/*!
			*	Called to indicate that we're beginning a dictionary entry in an object
			*	@param	key		The key. May or may not be NULL terminated
			*	@param	length	The length of the key
			*	@note	May be called in any order
			*/
			virtual void BeginObjectValue(const char* key, size_t length) = 0;

			/*!
			*	Called to indicate that we're ending a dictionary entry in an object
			*	@param	key		The key. May or may not be NULL terminated
			*	@param	length	The length of the key
			*/
			virtual void EndObjectValue(const char* key, size_t length) = 0;

			/*!
			*	Called to indicate a boolean value
			*	@param	boolean	The boolean value
			*/
			virtual void Boolean(bool boolean) = 0;

			/*!
			*	Called to indicate a Number value
			*	@param	number	The number value
			*/
			virtual void Number(BaseTypeFloat number) = 0;

			/*!
			*	Called to indicate a String value
			*	@param	str		The string. May or may not be NULL terminated
			*	@param	length	The length of the string
			*/
			virtual void String(const char* str, size_t length) = 0;

			/*!
			*	Called to indicate a Function value
			*	@param	function	The function value
			*/
			virtual void Function(EA::Types::FunctionIn function) = 0;

			/*!
			*	Called to indicate a UserData value
			*	@param	userData	The UserData value
			*/
			virtual void UserData(EA::Types::UserDataIn userData) = 0;

			/*!
			*	Called to indicate a Null value
			*/
			virtual void Null() = 0;
		};

		/*! @class IEncoderImpl iencoder.h	"EABaseTypes/iencoder.h"
		*	@brief template for implementing the IEncoder interface using any arbitrary Encoder
		*	@tparam	Encoder	The encoder type
		*/
		template<typename Encoder>
		class IEncoderImpl : public IEncoder
		{
		public:

			/*!
			*	IEncoderImpl constructor
			*	@param	params	The parameters for the encoder type
			*/
			inline IEncoderImpl(Encoder* encoder):mEncoder(encoder) {}

			// IEncoder implementation
			virtual void Reset() { mEncoder->Reset(); }

			virtual void BeginArray() { mEncoder->BeginArray(); }
			virtual void EndArray() { mEncoder->EndArray(); }

			virtual void BeginArrayValue(size_t index) { mEncoder->BeginArrayValue(index); }
			virtual void EndArrayValue(size_t index) { mEncoder->EndArrayValue(index); }

			virtual void BeginObject() { mEncoder->BeginObject(); }
			virtual void EndObject() { mEncoder->EndObject(); }

			virtual void BeginObjectValue(const char* key, size_t length) { mEncoder->BeginObjectValue(key, length); }
			virtual void EndObjectValue(const char* key, size_t length) { mEncoder->EndObjectValue(key, length); }

			virtual void Boolean(bool boolean) { mEncoder->Boolean(boolean); }
			virtual void Number(BaseTypeFloat number) { mEncoder->Number(number); }
			virtual void String(const char* str, size_t length) { mEncoder->String(str, length); }
			virtual void Function(EA::Types::FunctionIn function) { mEncoder->Function(function); }
			virtual void UserData(EA::Types::UserDataIn userData) { mEncoder->UserData(userData); }
			virtual void Null() { mEncoder->Null(); }

			Encoder* mEncoder;
		};
	}
}

#endif /* EABASETYPES_IENCODER_H_ */
