/*
 *
 *  D-Bus++ - C++ bindings for D-Bus
 *
 *  Copyright (C) 2005-2007  Paolo Durante <shackan@gmail.com>
 *
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <cassert>
#include <errno.h>

#include <dbus-c++/eventloop.h>
#include <dbus-c++/debug.h>

#include <sys/poll.h>
#include <sys/time.h>

#include <dbus/dbus.h>

using namespace DBus;

static double millis(timeval tv)
{
	return (tv.tv_sec *1000.0 + tv.tv_usec/1000.0);
}
	
DefaultTimeout::DefaultTimeout(int interval, bool repeat, DefaultMainLoop *ed)
: _enabled(true), _interval(interval), _repeat(repeat), _expiration(0), _data(0), _disp(ed)
{
	timeval now;
	gettimeofday(&now, NULL);

	_expiration = millis(now) + interval;

	_disp->_mutex_t.lock();
	_disp->_timeouts.push_back(this);
	_disp->_mutex_t.unlock();
}

DefaultTimeout::~DefaultTimeout()
{
	_disp->_mutex_t.lock();
	_disp->_timeouts.remove(this);
	_disp->_mutex_t.unlock();
}

DefaultWatch::DefaultWatch(int fd, int flags, DefaultMainLoop *ed)
: _enabled(true), _fd(fd), _flags(flags), _state(0), _data(0), _disp(ed)
{
	_disp->_mutex_w.lock();
	_disp->_watches.push_back(this);
	_disp->_mutex_w.unlock();
}

DefaultWatch::~DefaultWatch()
{
	_disp->_mutex_w.lock();
	_disp->_watches.remove(this);
	_disp->_mutex_w.unlock();
}

DefaultMutex::DefaultMutex()
{
	pthread_mutexattr_t attr;
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
	pthread_mutex_init(&_mutex, &attr);
}

DefaultMutex::~DefaultMutex()
{
	pthread_mutex_destroy(&_mutex);
}

void DefaultMutex::lock()
{
	int r = pthread_mutex_lock(&_mutex);
	/* This assert is here to avoid a difficult-to-diagnose deadlock. See
	 * crosbug.com/8486 and crosbug.com/8596. */
	assert(r != EDEADLK);
}

void DefaultMutex::unlock()
{
	pthread_mutex_unlock(&_mutex);
}

DefaultMainLoop::DefaultMainLoop()
{
	  _fdunlock[0] = -1;
	  _fdunlock[1] = -1;
}

DefaultMainLoop::~DefaultMainLoop()
{
	_mutex_w.lock();

	DefaultWatches::iterator wi = _watches.begin();
	while (wi != _watches.end())
	{
		DefaultWatches::iterator wmp = wi;
		++wmp;
		_mutex_w.unlock();
		delete (*wi);
		_mutex_w.lock();
		wi = wmp;
	}
	_mutex_w.unlock();

	_mutex_t.lock();

	DefaultTimeouts::iterator ti = _timeouts.begin();
	while (ti != _timeouts.end())
	{
		DefaultTimeouts::iterator tmp = ti;
		++tmp;
		_mutex_t.unlock();
		delete (*ti);
		_mutex_t.lock();
		ti = tmp;
	}
	_mutex_t.unlock();
}

void DefaultMainLoop::dispatch()
{
	_mutex_w.lock();

	int nfd = _watches.size();

	if (_fdunlock[0] >= 0 && _fdunlock[1] >= 0)
	{
		nfd=nfd+2;
	}

	pollfd fds[nfd];

	DefaultWatches::iterator wi = _watches.begin();

	for (nfd = 0; wi != _watches.end(); ++wi)
	{
		if ((*wi)->enabled())
		{
			fds[nfd].fd = (*wi)->descriptor();
			fds[nfd].events = (*wi)->flags();
			fds[nfd].revents = 0;

			++nfd;
		}
	}

	if (_fdunlock[0] >= 0 && _fdunlock[1] >= 0)
	{
		fds[nfd].fd = _fdunlock[0];
		fds[nfd].events = POLLIN | POLLOUT | POLLPRI ;
		fds[nfd].revents = 0;
		
		nfd++;
		fds[nfd].fd = _fdunlock[1];
		fds[nfd].events = POLLIN | POLLOUT | POLLPRI ;
		fds[nfd].revents = 0;
	}

	_mutex_w.unlock();

	int wait_min = -1;

	DefaultTimeouts::iterator ti;

	_mutex_t.lock();

	for (ti = _timeouts.begin(); ti != _timeouts.end(); ++ti)
	{
		if (((*ti)->enabled() && (*ti)->interval() < wait_min) || (wait_min < 0))
			wait_min = (*ti)->interval();
	}

	_mutex_t.unlock();

	poll(fds, nfd, wait_min);

	timeval now;
	gettimeofday(&now, NULL);

	double now_millis = millis(now);

	_mutex_t.lock();

	ti = _timeouts.begin();

	while (ti != _timeouts.end())
	{
		DefaultTimeouts::iterator tmp = ti;
		++tmp;

		if ((*ti)->enabled() && now_millis >= (*ti)->_expiration)
		{
			(*ti)->expired(*(*ti));

			if ((*ti)->_repeat)
			{
				(*ti)->_expiration = now_millis + (*ti)->_interval;
			}

		}

		ti = tmp;
	}

	_mutex_t.unlock();

	_mutex_w.lock();

	for (int j = 0; j < nfd; ++j)
	{
		DefaultWatches::iterator wi;

		for (wi = _watches.begin(); wi != _watches.end();)
		{
			DefaultWatches::iterator tmp = wi;
			++tmp;

			if ((*wi)->enabled() && (*wi)->_fd == fds[j].fd)
			{
				if (fds[j].revents)
				{
					(*wi)->_state = fds[j].revents;

					(*wi)->ready(*(*wi));

					fds[j].revents = 0;
				}
			}

			wi = tmp;
		}
	}
	_mutex_w.unlock();
}

