#ifndef XMMSCLIENTPP_MAINLOOP_H
#define XMMSCLIENTPP_MAINLOOP_H

#include <xmmsclient/xmmsclient++/listener.h>

#include <list>


namespace Xmms 
{

	/** @class MainloopInterface mainloop.h "xmmsclient/xmmsclient++/mainloop.h"
	 *  @brief Interface to all mainloops run by Client.
	 */
	class MainloopInterface
	{

		public:

			/** Constructor.
			 *
			 *  @param conn xmmsc_connection_t* of the connection to
			 *              use in the mainloop.
			 *
			 *  @note The constructor should only initialize the
			 *        mainloop, not start it!
			 */
			MainloopInterface( xmmsc_connection_t* conn ) :
				running_( false ), conn_( conn ) { }

			/** Destructor.  Should also stop the loop.
			 */
			virtual ~MainloopInterface() { }

			/** Start the mainloop.
			 *
			 * @note Some mainloop implementations might require the
			 *       use of a separate function to be run.
			 */
			virtual void run() = 0;

			/** Check if the mainloop is currently running.
			 */
			bool isRunning() const {
				return running_;
			}

		protected:
			bool running_;
			xmmsc_connection_t*& conn_;

	};

	/** @class MainLoop mainloop.h "xmmsclient/xmmsclient++/mainloop.h"
	 *  @brief A standalone mainloop allowing additional custom Listeners.
	 *  Can only be created by the Client class.
	 */
	class MainLoop : public MainloopInterface
	{

		public:
			/** Copy-constructor.
			 */
			MainLoop( const MainLoop& src );

			/** Destructor.
			 *
			 * @note The destructors frees all the registered listeners.
			 */
			virtual ~MainLoop();

			/** Add a new listener to listen on in the loop.
			 */
			void addListener( ListenerInterface* l );

			/** Remove an existing listener from the loop.
			 *
			 * @note The ListenerInterface comparison operator is used
			 *       (i.e. compare the file descriptors), not pointer
			 *       comparison.
			 */
			void removeListener( ListenerInterface* l );

			/** Start the mainloop.
			 *  Only stops if the connection is lost or all listeners
			 *  are removed.
			 */
			virtual void run();

		/** @cond */
		private:

			// Constructor, only to be called by Xmms::Client
			friend class Client;

			/** Constructor, only callable by Client.
			 *
			 *  @param conn xmmsc_connection_t* of the connection used
			 *              in the mainloop.
			 */
			MainLoop( xmmsc_connection_t*& conn );

			/** Copy assignment operator, only callable by Client.
			 */
			MainLoop& operator=( const MainLoop& src ) const;

			/** List of listeners listened on.
			 */
			std::list< ListenerInterface* > listeners;

			/** The method actually doing the io operations on the
			 *  listeners.
			 */
			void waitForData();

		/** @endcond */
	};

}

#endif // XMMSCLIENTPP_MAINLOOP_H
