/*---------------------------------------------------------------
	FILE: C2DRangeFinderAbstract.h
	USE: See doxygen doc.

   Part of the MRPT Library
   ISA - Universidad de Malaga - http://www.isa.uma.es
  ---------------------------------------------------------------*/
#ifndef C2DRangeFinderAbstract_H
#define C2DRangeFinderAbstract_H

#include <MRPT/UTILS/CStream.h>
#include <MRPT/UTILS/SYNCH.h>
#include <MRPT/UTILS/CDebugOutputCapable.h>
#include <MRPT/MRML/CObservation2DRangeScan.h>
#include <MRPT/UTILS/CConfigFileBase.h>

namespace HWDRIVERS
{
	/** This is the base, abstract class for "software drivers" interfaces to 2D scanners (laser range finders).
	  *  Physical devices may be interfaced through a serial port, a USB connection,etc. but this class
	  *   abstract those details throught the "binding" of the specific scanner driver to a given I/O channel,
	  *   which must be set by calling "HWDRIVERS::C2DRangeFinderAbstract::bindIO". See also the derived classes.
	  *
	  * \sa HWDRIVERS::CSerialPort
	  */
	class C2DRangeFinderAbstract : public CDebugOutputCapable
	{
	private:
		MRML::CObservation2DRangeScan	m_lastObservation;
		bool							m_lastObservationIsNew;
		bool							m_hardwareError;

		/** For being thread-safe.
		  */
		UTILS::SYNCH::CCriticalSection	m_csChangeStream,m_csLastObservation;

	protected:
		/** The I/O channel (will be NULL if not bound).
		  */
		UTILS::CStream					*m_stream;

	public:

		/** Default constructor
		  */
		C2DRangeFinderAbstract();

		/** Destructor
		  */
		virtual ~C2DRangeFinderAbstract();

		/** Binds the object to a given I/O channel.
		  *  The stream object must not be deleted before the destruction of this class.
		  * \sa HWDRIVERS::CSerialPort
		  */
		void  bindIO( CStream	*streamIO );

		/** Get the last observation from the sensor, if available, and unmarks it as being "the last one" (thus a new scan must arrive or subsequent calls will find no new observations).
		  */
		void  getObservation(
			bool							&outThereIsObservation,
			MRML::CObservation2DRangeScan	&outObservation,
			bool							&hardwareError );

		/** Specific laser scanner "software drivers" must process here new data from the I/O stream, and, if a whole scan has arrived, return it.
		  *  This method MUST BE CALLED in a timely fashion by the user to allow the proccessing of incoming data. It can be run in a different thread safely.
		  */
		virtual void  doProcess(
			bool							&outThereIsObservation,
			MRML::CObservation2DRangeScan	&outObservation,
			bool							&hardwareError ) = 0;

		/** Loads specific configuration for the device from a given source of configuration parameters, for example, an ".ini" file, loading from the section "[iniSection]" (see UTILS::CConfigFileBase and derived classes)
		  */
		virtual void  loadConfig(
			const CConfigFileBase *configSource,
			const std::string	  &iniSection ) = 0;

		/** Enables the scanning mode (which may depend on the specific laser device); this must be called before asking for observations to assure that the protocol has been initializated.
		  * \return If everything works "true", or "false" if there is any error.
		  */
		virtual bool  turnOn() = 0;

		/** Disables the scanning mode (this can be used to turn the device in low energy mode, if available)
		  * \return If everything works "true", or "false" if there is any error.
		  */
		virtual bool  turnOff() = 0;


	};	// End of class

} // End of namespace


#endif
