/** @file iproxy.h
*	Proxy interface
*	@author Chris Burns (cburns@ea.com)
*
*	(c) 2013 Electronic Arts Inc.
*/

#ifndef EABASETYPESPLUS_IPROXY_H_
#define EABASETYPESPLUS_IPROXY_H_

#include "EABaseTypes/autoref.h"

#include "EABaseTypesPlus/irefcounted.h"

namespace EA
{
	class String;

	namespace Types
	{
		class Factory;

		EABASETYPES_FORWARD_DECLARATION(class, Array)
		EABASETYPES_FORWARD_DECLARATION(class, BaseType)
		EABASETYPES_FORWARD_DECLARATION(class, Function)
		EABASETYPES_FORWARD_DECLARATION(class, Object)
		EABASETYPES_FORWARD_DECLARATION(class, UserData)

		EABASETYPES_FORWARD_DECLARATION(class, IProxy)

		bool ProxyPathNext(const char*& path, EA::String& name);
		bool ProxyPathHasNext(const char* path);

		/*! @class IProxy iproxy.h	"EABaseTypesPlus/iproxy.h"
		*	@brief Virtual interface for a proxy
		*/
		class IProxy : public IRefCounted
		{
		public:

			virtual ~IProxy() {}

			static IProxyReturn AsIProxyRef(BaseTypeIn baseType);

			/*!
			*	Retrieve this interface as an object
			*	@return	ObjectReturn	A collection of functions representing this object
			*/
			virtual ObjectReturn ToObject() = 0;

			/*!
			*	Retrieve this interface a userdata
			*	@param	factory			The factory to use for creating the userdata
			*	@return	UserDataReturn	An IProxyRef wrapped as a UserData
			*/
			UserDataReturn ToUserData(Factory* factory);
            
            /*!
            *   Recursively list the contents of the proxy
            *   @param  FunctionIn      The function to call with the data
            *   @param  ArrayIn         Previously visited proxies
            */
            virtual void List(FunctionIn callback, ArrayIn visited) = 0;

			/*!
			*	Get a proxied function
			*	@param	path			The path to the proxied function
			*	@return	FunctionReturn	The proxied function
			*/
			virtual FunctionReturn GetFunction(const char *path) = 0;

			/*!
			*	Get a proxied object
			*	@param	path			The path to the proxied interface
			*	@param	schema			A schema for the interface (an array of function names)
			*	@return	ObjectReturn	The proxied interface
			*/
			virtual ObjectReturn GetInterface(const char* path, ArrayIn schema) = 0;

			/*!
			*	Get a proxied object
			*	@param	path			The path to the proxied interface
			*	@param	schema			A schema for the interface (an array of function names)
			*	@return	ObjectReturn	The proxied interface
			*/
			virtual ObjectReturn GetInterface(const char* path, const char** schema) = 0;

		protected:

			ObjectReturn GetInterface(Factory* factory, const char* path, const char** schema);
		};
	}
}

#endif /* EABASETYPESPLUS_IPROXY_H_ */
