/** @file inav.h
 *  Abstract class representing the formal interface for the navigation system
 *	@author Chris Burns (cburns@ea.com)
 *
 *	UX
 *	(c) 2012 Electronic Arts Inc. 
 */

#ifndef EANAV_INAV_H_
#define EANAV_INAV_H_

#include "EABaseTypes/datatypes.h"

namespace EA
{
	namespace Nav
	{
		/*! @class	INav inav.h	"EANav/inav.h"
		*	@brief	virtual interface representing a navigation system
		*/
		class INav
		{
		public:

			static const char* SCHEMA[];

			virtual ~INav() {}

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

			/*!
			*	Start the navigation system
			*	@param[in] callback				the callback to call once the navigation system has been started (will be called with zero arguments)
			*/
			virtual void Start(EA::Types::FunctionIn callback) = 0;

			/*!
			*	Have the navigation system process an event
			*	@param[in] callback				the callback to call once the event has been processed (will be called with zero arguments)
			*	@param[in] name					the name of the event
			*	@param[in] data					the data associated with the event
			*/
			virtual void Event(EA::Types::FunctionIn callback, const char* name, EA::Types::BaseTypeIn data) = 0;

			/*!
			*	Add a handler for a named action
			*	@param[in]	name				The name of the action we're adding the handler for
			*	@param[in]	async				Whether or not the action is asynchronous
			*	@param[in]  read				The data that we want to read when this action is triggered (event, transition, variables, etc)
			*	@param[in]	handler				The handler that will be called when the named action needs to be performed 
			*									(will receive a Function, a String, an Object, and further parameters 
			*									representing 
			*										the callback for the action (which can be called with arbitrary parameters dependent on the action implementation) (only for asynchronous actions)
			*										the name of the action
			*										the data requested in the read parameter
			*										the parameters for the action)						
			*/
			virtual void AddActionHandler(const char* name, bool async, EA::Types::ArrayIn read, EA::Types::FunctionIn handler) = 0;

			/*!
			*	Add a handler for a named action
			*	@param[in]	name				The name of the action we're adding the handler for
			*	@param[in]	async				Whether or not the action is asynchronous
			*	@param[in]  read				The data that we want to read when this action is triggered (event, transition, variables, etc)
			*	@param[in]	handler				The handler that will be called when the named action needs to be performed 
			*									(will receive a Function, a String, an Object, and further parameters 
			*									representing 
			*										the callback for the action (which can be called with arbitrary parameters dependent on the action implementation) (only for asynchronous actions)
			*										the name of the action
			*										the data requested in the read parameter (only for actions added with a non-NULL, non-empty read parameter)
			*										the parameters for the action)						
			*/
			virtual void AddActionHandler(const char* name, bool async, const char** read, EA::Types::FunctionIn handler) = 0;

			/*!
			*	Remove a handler for a named action
			*	@param[in]	name				The name of the action we're removing the handler for		
			*/
			virtual void RemoveActionHandler(const char* name) = 0;

			/*!
			*	Set the failure handler for nav states
			*	@param[in]	handler				The handler that will be called when a nav state cannot be loaded
			*/
			virtual void SetLoadFailureHandler(EA::Types::FunctionIn handler) = 0;
		
			/*!
			*	Save the current configuration as a data structure
			*	@param[in]	callback			The callback to be called with the saved configuration
			*/
			virtual void SaveConfiguration(EA::Types::FunctionIn callback) = 0;
		
			/*!
			*	Load a saved configuration
			*	@param[in]	callback			The callback to be called once the configuration is loaded
			*/
			virtual void LoadConfiguration(EA::Types::FunctionIn callback, EA::Types::BaseTypeIn configuration) = 0;

            /*!
			*	Add a listener
			*	@param[in]	name				An identifier for the listener
			*	@param[in]	filter				The list of events to listen to
			*	@param[in]	listener			The listener to add
			*	@attention						This method should only be used for development purposes, or for telemetry, not for production code
			*									is is WRONG to care about events and states - that's why there are actions
			*/
			virtual void AddListener(const char* name, EA::Types::ArrayIn filter, EA::Types::FunctionIn listener) = 0;

			/*!
			*	Add a listener
			*	@param[in]	name				An identifier for the listener
			*	@param[in]	filter				The list of events to listen to (a NULL terminated array of const char*'s)
			*	@param[in]	listener			The listener to add				
			*	@attention						This method should only be used for development purposes, or for telemetry, not for production code
			*									is is WRONG to care about events and states - that's why there are actions
			*/
			virtual void AddListener(const char* name, const char** filter, EA::Types::FunctionIn listener) = 0;

			/*!
			*	Remove a listener
			*	@param[in]	name				The identifier of the listener to remove
			*	@attention						This method should only be used for development purposes, or for telemetry, not for production code
			*									is is WRONG to care about events and states - that's why there are actions
			*/
			virtual void RemoveListener(const char* name) = 0;
            
#if !defined(EA_FINAL)

			/*!
			*	Get the names of the states in the current configuration of the navigation system
			*	@param[in]	callback			The callback to called with the list of names
			*	@attention						This method should only be used for development purposes, not for production code
			*/
			virtual void GetStates(EA::Types::FunctionIn callback) = 0;

			/*!
			*	Get all events that have transitions for the current configuration
			*	@param[in]	callback			The callback to called with the list of events
			*	@attention						This method should only be used for development purposes, not for production code
			*/
			virtual void GetTransitionEvents(EA::Types::FunctionIn callback) = 0;

			/*!
			*	Have the navigation automatically navigate to a configuration with the given states
			*	@param[in] callback				The callback to call once the automatic navigation is completed
			*	@param[in] defaultHandler		The function to call for uninteresting events
			*	@param[in] hintFile				The name of a file containing hints for what to do with unusual events
			*	@param[in] excludeFile			The name of a file containing a list of events to exclude from the path
			*	@param[in] targets				An array of target states (these are just fully qualified names)
			*	@param[in] maxNodes				How many nodes to search
			*	@attention						This method should only be used for development purposes, not for production code
			*/
			virtual void Auto(EA::Types::FunctionIn callback, 
							  EA::Types::FunctionIn defaultHandler,
							  const char* hintFile, 
							  const char* excludeFile, 
							  EA::Types::ArrayIn targets, 
							  int maxNodes) = 0;

			/*!
			*	@param[in]	name				The name of the auto handler we're adding
			*	@param[in]	handler				The handler function that will be called when the named auto handler needs to be performed
			*									(will receive a Function, a String, and further parameters, 
			*									representing 
			*										the callback for the handler
			*										the name of the handler
			*										the parameters for the handler
			*/
			virtual void AddAutoHandler(const char* name, EA::Types::FunctionIn handler) = 0;

			/*!
			*	@param[in]	name				The name of the auto handler we're removing
			*/
			virtual void RemoveAutoHandler(const char* name) = 0;
            
            virtual void GetConfiguration(EA::Types::FunctionIn callback) = 0;
            
            virtual void Reload(EA::Types::FunctionIn callback, const char* name) = 0;
#endif // !EA_FINAL
		};
	}
}

#endif /* EANAV_INAV_H_ */
