/** @file luafunction.h
*	Definition of lua implementation for EA::Types::Function interface
*	@author Nick Beatty (nbeatty@ea.com)
*
*	UX
*	(c) 2012 Electronic Arts Inc.
*/

#ifndef EABASETYPESLUA_LUAFUNCTION_H
#define EABASETYPESLUA_LUAFUNCTION_H

#include "EABaseTypes/datatypes.h"
#include "EABaseTypes/profile.h"

//lint -e961
// Violates MISRA Advisory Rule 19.1, only preprocessor statements and comments before '#include'
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
}

#include "EABaseTypesLua/EABaseTypesLua.h"
#include "EABaseTypesLua/luaencoder.h"

namespace EA
{
	namespace Lua
	{
		/*!
		*	Template function for adding an optimized caller to LUA
		*	@tparam Decoder	The argument decoder type for the caller
		*	@tparam	Encoder The result encoder type for the caller
		*	@param	id		The unique id for the caller
		*/
		template<template<class> class Decoder, class Encoder>
		void AddCaller(EA::Types::CallerMap* callerMap, unsigned int id)
		{
			callerMap->Add(Lua::CALLER_TYPE, id, Decoder<LuaEncoder>::Decode, LuaDecoder<Encoder>::Decode);
		}

		/*! @class LuaFunction ux_luafunction.h	"ux_lua/ux_luafunction.h"
		*	@brief Stores a reference to a LUA function as a BaseType
		*/
		class LuaFunction : public EA::Types::Function
		{
		public:

			/*!
			*	LuaFunction C'tor
			*	@param[in]	L	pointer to Lua State
			*	@param[in]	index lua stack index where function is
			*/
			LuaFunction(EA::Types::Factory* factory, lua_State* L, int index);
			virtual ~LuaFunction();

			/*!
			*	Create a deep copy of this object
			*	@return	BaseType*	A deep copy of this object
			*/
			virtual EA::Types::BaseTypeReturn Clone();

			/*!
			*	Call the function
			*	@param	id				The id for the caller
			*	@param	decoderParams	The argument decoder params for this caller
			*	@param	encoder			The result encoder for this caller
			*	@param	defaultDecode	The default argument decode function to use if none is available (expects an IEncoder as the first parameter)
			*	@param	defaultEncoder	The default result encoder to use if not result decode function is available
			*/
			virtual void Call(unsigned int id, 
							  void* decoderParams,
							  void* encoder,
							  EA::Types::DecodeFunction defaultDecode,
							  EA::Types::IEncoder* defaultEncoder);
			
			using EA::Types::Function::Call;

			/*!
			*	Compare two functions
			*	@param[in] Function*	Function to compare to
			*	@return bool True iff the functions are equal, false otherwise
			*/
			virtual bool Equals(EA::Types::FunctionIn pCompare);

			/*!
			*	Compare two functions
			*	@return unsigned int The id defined to this type of Function class
			*	@todo This is generally used only by the Equals Function and should go away when we start using SafeCom 
			*/
			virtual EA::Type::TypeID GetFunctionType() { return EA::Type::TypeOf(*this); }

			
			/*!
			*	Get the registry reference for the lua function
			*	@return int the registry reference for the lua function
			*/
			int GetRef() { return mRef; }

			/*!
			*	Get the Lua state for this function
			*	@return lua_State* The lua state for this function
			*/
			lua_State* GetLuaState() { return mL; }


		private:
			
			lua_State*	mL;
			int			mRef;
		};

	}
}

#endif /* EABASETYPESLUA_LUAFUNCTION_H */

