/*
 * Copyright 2009  Gregory Haynes <greg@greghaynes.net>
 *
 * This program 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 2 of
 * the License, or (at your option) any later version.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef QINFINITY_QTIO_H
#define QINFINITY_QTIO_H

#include <libinfinity/common/inf-io.h>

#include <QObject>
#include <QList>
#include <QHash>
#include <QTimer>
#include <QEvent>
#include <QLinkedList>
#include <QMutex>

namespace QInfinity
{

class QtIo;
class QtIoWatch;
class InfEvent;

typedef struct _QInfQtIoClass QInfQtIoClass;
typedef struct _QInfQtIo QInfQtIo;

/**
 * @brief Event handler interface for libinfinity.
 */
class QtIo
	: public QObject
{

	public:
		static QtIo *instance();

		QtIo( QObject *parent = 0 );
		virtual ~QtIo();

		virtual InfIoWatch *addWatch( InfNativeSocket *socket,
			InfIoEvent events,
			InfIoWatchFunc func,
			gpointer user_data,
			GDestroyNotify notify );
		virtual void updateWatch( InfIoWatch *watch,
			InfIoEvent events );
		virtual void removeWatch( InfIoWatch *watch );

		virtual InfIoTimeout *addTimeout( unsigned int msecs,
			InfIoTimeoutFunc func,
			void *user_data,
			GDestroyNotify notify );
		virtual void removeTimeout( InfIoTimeout *timer );

		virtual InfIoDispatch *addDispatch( InfIoDispatchFunc func,
			gpointer user_data,
			GDestroyNotify notify );
		virtual void removeDispatch( InfIoDispatch *dispatch );

		virtual bool event( QEvent *e );

		GObject *gobject() const;
		void setOwner( bool own_gobject );
	
	private:
		QInfQtIo *m_gobject;
		bool own_gobject;
		QHash<int, QtIoWatch*> socketToWatchMap;
		QLinkedList<InfEvent*> cancelledEvents;
		QMutex cancelledEventsMutex;

};

/**
 * @brief Timer for QtIo
 */
class InfTimer
	:  public QTimer
{
	Q_OBJECT;

	public:
		InfTimer( unsigned int msecs,
			InfIoTimeoutFunc func,
			void *user_data,
			GDestroyNotify notify,
			QObject *parent = 0 );
		~InfTimer();

		void activate();

	private Q_SLOTS:
		void activated();

	private:
		InfIoTimeoutFunc m_func;
		void *m_user_data;
		GDestroyNotify m_notify;

};

/**
 * @brief QEvent wrapper for addDispatch/postEvent
 */
class InfEvent
	:  public QEvent
{
	public:
		InfEvent( InfIoDispatchFunc func,
			gpointer user_data,
			GDestroyNotify notify );
		~InfEvent();

		void call();

	private:
		InfIoDispatchFunc m_func;
		gpointer m_user_data;
		GDestroyNotify m_notify;
};

}

#endif

