/* +---------------------------------------------------------------------------+
   |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
   |                                                                           |
   |                   http://mrpt.sourceforge.net/                            |
   |                                                                           |
   |   Copyright (C) 2005-2008  University of Malaga                           |
   |                                                                           |
   |    This software was written by the Perception and Robotics               |
   |      research group, University of Malaga (Spain).                        |
   |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
   |                                                                           |
   |  This file is part of the MRPT project.                                   |
   |                                                                           |
   |     MRPT is free software: you can redistribute it and/or modify          |
   |     it under the terms of the GNU General Public License as published by  |
   |     the Free Software Foundation, either version 3 of the License, or     |
   |     (at your option) any later version.                                   |
   |                                                                           |
   |   MRPT is distributed in the hope that it will be useful,                 |
   |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
   |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
   |     GNU General Public License for more details.                          |
   |                                                                           |
   |     You should have received a copy of the GNU General Public License     |
   |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
   |                                                                           |
   +---------------------------------------------------------------------------+ */
#ifndef CActionCollection_H
#define CActionCollection_H

#include <MRPT/MRML/CAction.h>
#include <MRPT/MRML/CActionRobotMovement2D.h>
#include <MRPT/UTILS/CSerializable.h>

namespace MRML
{
	/** Declares a class for storing a collection of robot actions. It is used in MRML::CActionObservationSequence,
	 *    for logs storage and particle filter based simulations.
     *
	 * \sa CAction, CActionObservationSequence
	 */
	class CActionCollection : public UTILS::CSerializable
	{
		// This must be added to any CSerializable derived class:
		DEFINE_SERIALIZABLE( CActionCollection )

	protected:
		/** The actions:
		  */
		std::deque<CAction*>	m_actions;

	 public:
		 /** Constructor
		   */
		CActionCollection();

		/** Constructor from a single action.
		   */
		CActionCollection( CAction &a );

		/** Copy Constructor
		   */
		CActionCollection(const CActionCollection &o );

		/** Copy operator
		  */
		CActionCollection&  operator = (const CActionCollection &o );

		/** Destructor
		   */
		~CActionCollection();

		/** You can use CActionCollection::begin to get a iterator to the first element.
		  */
		typedef std::deque<CAction*>::iterator		iterator;

		/** You can use CActionCollection::begin to get a iterator to the first element.
		  */
		typedef std::deque<CAction*>::const_iterator	const_iterator;

		/** Returns a iterator to the first action: this is an example of usage:
		  * \code
		  *   CActionCollection  acts;
		  *   ...
		  *   for (CActionCollection::iterator it=acts.begin();it!=acts.end();it++)
		  *	  {
		  *      (*it)->... // (*it) is a "CAction*"
		  *   }
		  *
		  * \endcode
		  */
		const_iterator begin() const { return m_actions.begin(); }

		/** Returns a iterator to the first action: this is an example of usage:
		  * \code
		  *   CActionCollection  acts;
		  *   ...
		  *   for (CActionCollection::iterator it=acts.begin();it!=acts.end();it++)
		  *	  {
		  *      (*it)->... // (*it) is a "CAction*"
		  *   }
		  *
		  * \endcode
		  */
		iterator begin() { return m_actions.begin(); }

		/** Returns a iterator pointing to the end of the list: this is an example of usage:
		  * \code
		  *   CActionCollection  acts;
		  *   ...
		  *   for (CActionCollection::iterator it=acts.begin();it!=acts.end();it++)
		  *	  {
		  *      (*it)->... // (*it) is a "CAction*"
		  *   }
		  *
		  * \endcode
		  */
		const_iterator end() const { return m_actions.end(); }

		/** Returns a iterator pointing to the end of the list: this is an example of usage:
		  * \code
		  *   CActionCollection  acts;
		  *   ...
		  *   for (CActionCollection::iterator it=acts.begin();it!=acts.end();it++)
		  *	  {
		  *      (*it)->... // (*it) is a "CAction*"
		  *   }
		  *
		  * \endcode
		  */
		iterator end() { return m_actions.end(); }


		/** Removes the given action in the list, and return an iterator to the next element (or this->end() if it was the last one).
		  */
		iterator erase( const iterator &it);

		/** Erase all actions from the list.
		  */
		void  clear();

		/** Access the i'th action.DO NOT MODIFY the returned object, make a copy of ir with "CSerializable::duplicate" if desired.
		  *  First element is 0.
		  * \exception std::exception On index out of bounds.
		  */
		CAction	*  get(size_t index);

		/** Access the first action found with a desired class. Pass the desired class with CLASS_ID( classname )
		  *   DO NOT MODIFY the returned object, make a copy of ir with "CSerializable::duplicate" if desired.
		  * \returns The action, or NULL if not found.
		  */
		const CAction	*  getByClass(const  UTILS::TRuntimeClassId	*desired_class ) const;

		/** Add a new object to the list.
		  */
		void  insert(CAction	&action);

		/** Returns the actions count in the collection.
		  */
		size_t  size();

		/** Returns the best pose increment estimator in the collection, based on the determinant of its pose change covariance matrix.
		  * \return The estimation, or NULL if none is available.
		  */
		const CActionRobotMovement2D	*  getBestMovementEstimation() const;

		/** Returns the pose increment estimator in the collection having the specified type.
		  * \return The estimation, or NULL if none is available.
		  */
		CActionRobotMovement2D	*  getMovementEstimationByType( CActionRobotMovement2D::TEstimationMethod method);

		/** Remove an action from the list by its index.
		  * \exception std::exception On index out of bounds.
		  */
		void  eraseByIndex(const size_t & index);


	}; // End of class def.

	// This must be added to any CSerializable derived class:
	DEFINE_SERIALIZABLE_POST( CActionCollection )

} // End of namespace

#endif
