/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__NACE__
#define	__NACE__


		#include "nstring/nstring.h"
		#include "container/narray_list.h"
		#include "container/nlist.h"


namespace GS {
	namespace ACE {
		class Manager;

static const int max_command_param = 3;	///	Maximum number of parameters to a command.

#define	AceCommandNop	-1		///< No operator (can be used to pause execution (ie: "Nop 1000;" will pause 1 sec)).
#define	AceCommandExec	-2		///< Internal use.
#define	AceCommandLoop	-3		///< Loop position.
#define	AceCommandNext	-4		///< Reset PC back to the loop position (default: 0, reset script).

/*!
	@short	ACE base command.
	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
struct	Command
{
		int			code;						///< Command code.
		float		duration,					///< Command duration in ms.
					duration_left,				///< Command duration still left to execute in ms.
					parm[max_command_param];	///< Command parameter.

		bool		operator == (const Command &other)
		{
			if	((code != other.code) || (duration != other.duration))
				return false;
			for	(int n = 0; n < max_command_param; ++n)
				if	(parm[n] != other.parm[n])
					return false;
			return true;
		}

		/// Mark a command as executed in the pipeline.
		void		SetDone()
		{	duration_left = 0;	}
};

/*!
	@short	ACE (Asynchronous Command Execution) unit.
	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
class	Unit
{
		friend class Manager;

protected:

		bool		is_done;		// this flag is raised on the next update following the last command execution

		List <Command>	list;
		List <Command> ::Item *pc, *loop_pc;

		/// Execute a command.
virtual	bool		ExecCommand(Command *cmd, float dt);

public:

		bool		IsCommandListDone() const
		{	return is_done;	}

		void		DumpCommandList();
		void		ResetCommandList();

		Unit();
virtual	~Unit() {}
};

/*!
	@short	ACE command definition.
*/
struct	Define
{
		String		id;
		int			code;
		int			nparm;
};

/*!
	@short	ACE manager.

	ACE is a mini script system that provides a way to automate
	the execution of a series of actions on an object.

	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
class	Manager
{
		ArrayList <Define *> define_list;	///< List of defined command.

public:

		/*!
			@short	Load a string command list in a unit.
			@return	Number of generated commands, -1 on error.
		*/
		int			LoadACECommandList(const char *str, Unit *) const;
		/// Define a new command in the manager.
		bool		DefineACECommand(const char *command, int code, int nparm, bool user_code = true);
		/// Update a unit.
		void		UpdateACEUnit(Unit *, float dt);

		Manager();
virtual ~Manager();
};

	} // ACE
} // GS


#endif	// __NACE__
