/*
 *  Realtime timer with GLib integration
 *
 *  Copyright (C) 2014  Nest Labs. All rights reserved.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  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, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>

#include "timer.h"

/*
 * A GLib custom event source using a POSIX fd timer that becomes
 * 'ready' on timer expiration. Timer 'advances' across a suspend but
 * has no ability to bring system out of suspend. Timer will fire upon
 * resume if expired.
 */

typedef struct _GRTimeoutSource GRTimeoutSource;

struct _GRTimeoutSource
{
	GSource	source;
	GPollFD	pfd;
	guint interval;
        gpointer tag;
};

static gboolean g_rttimeout_prepare (GSource *source, gint *timeout);
static gboolean g_rttimeout_check (GSource *source);
static gboolean g_rttimeout_dispatch (GSource *source, GSourceFunc callback,
				     gpointer user_data);

GSourceFuncs g_rttimeout_funcs =
{
	g_rttimeout_prepare,
	g_rttimeout_check,
	g_rttimeout_dispatch,
	NULL
};

void g_rttimeout_info(const char *format, ...)
{
	va_list ap;

	va_start(ap, format);
	vsyslog(LOG_INFO, format, ap);
	va_end(ap);
}

static gboolean g_rttimeout_prepare (GSource *source, gint *timeout)
{
	*timeout = -1;

	return FALSE;
}

static gboolean g_rttimeout_check (GSource *source)
{
	GRTimeoutSource *timeout_source = (GRTimeoutSource *)source;

	return timeout_source->pfd.revents & G_IO_IN;
}

static gboolean
g_rttimeout_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
{
	GRTimeoutSource *timeout_source = (GRTimeoutSource *)source;
	gboolean again;

	g_rttimeout_info("DHCP: %s: fd=%d, source=%p, user_data=%p",
			__func__, timeout_source->pfd.fd, source, user_data);
	if (!callback) {
		g_warning ("GR timeout source dispatched without callback\n"
			   "You must call g_source_set_callback().");
		if (!g_source_is_destroyed (source)) {
			g_source_remove_poll (source, &timeout_source->pfd);
			close(timeout_source->pfd.fd);
		}
		return FALSE;
	}

	again = callback (user_data);

	if (again) {
		struct itimerspec timer_value;
		int result;

		/* arm the timer as a single-shot */
		timer_value.it_value.tv_sec = timeout_source->interval / 1000;
		timer_value.it_value.tv_nsec = (timeout_source->interval % 1000) * 1000000;
		timer_value.it_interval.tv_sec = 0;
		timer_value.it_interval.tv_nsec = 0;

		result = timerfd_settime (timeout_source->pfd.fd, 0,
					  &timer_value, NULL);
		if (result == -1)
			g_error ("%s: error calling timer_settime", G_STRLOC);
	} else {
		if (!g_source_is_destroyed (source)) {
			g_source_remove_poll (source, &timeout_source->pfd);
			close(timeout_source->pfd.fd);
		}
	}

	return again;
}

/**
 * g_rttimeout_add_seconds_full:
 */
guint g_rttimeout_add_seconds_full (gint type, gint priority, guint32 interval,
				   GSourceFunc function, gpointer data,
				   GDestroyNotify notify)
{
  return g_rttimeout_add_full(type, priority, interval * 1000,
				   function, data, notify);
}

/**
 * g_rttimeout_add_full:
 */
guint g_rttimeout_add_full (gint type, gint priority, guint32 interval,
			   GSourceFunc function, gpointer data,
			   GDestroyNotify notify)
{
	GSource *source;
	int fd;
	guint id;
        gpointer tag;

	g_return_val_if_fail (function != NULL, 0);

	source = g_source_new (&g_rttimeout_funcs, sizeof (GRTimeoutSource));
	if (priority != G_PRIORITY_DEFAULT)
		g_source_set_priority (source, priority);
	g_source_set_callback (source, function, data, notify);
	id = g_source_attach (source, NULL);
	g_source_unref (source);

	fd = timerfd_create(type, 0);
	if (fd != -1) {
		GRTimeoutSource *timeout_source = (GRTimeoutSource *)source;
		struct itimerspec timer_value;
		int result;

		g_rttimeout_info("DHCP: %s: id=%d fd=%d, source=%p, seconds=%d",
				__func__, id, fd, source, interval/1000);
		memset(&timer_value, 0, sizeof(struct itimerspec));

		timer_value.it_value.tv_sec = interval / 1000;
		timer_value.it_value.tv_nsec = (interval % 1000) * 1000000;

		/* arm the timer as a single-shot */
		result = timerfd_settime (fd, 0, &timer_value,
					  NULL);
		if (result != -1) {
			timeout_source->interval = interval;
			timeout_source->pfd.fd = fd;
			timeout_source->pfd.events = G_IO_IN;

                        tag = g_source_add_unix_fd(source, fd, G_IO_IN);

                        if (tag != NULL) {
                            timeout_source->tag = tag;
                        } else {
                            g_rttimeout_info("DHCP: %s: cannot attach fd to source\n", __func__);
                            g_error ("%s: error calling g_source_add_unix_fd", G_STRLOC);
                        }
		} else {
			g_rttimeout_info("DHCP: %s: error timerfd_settime, err=%d\n",
				__func__, errno);
			g_error ("%s: error calling timerfd_settime", G_STRLOC);
		}
	} else {
		g_error ("%s: error calling timerfd_create (type=%d err=%d)", G_STRLOC, type, errno);
	}

	return id;
}

gboolean g_rttimeout_source_remove(guint id)
{
	GSource *source;

	g_return_val_if_fail (id > 0, FALSE);
	source = g_main_context_find_source_by_id (NULL, id);
	if (source) {
		GRTimeoutSource *timeout_source = (GRTimeoutSource *)source;

		if (!g_source_is_destroyed (source)) {
			g_rttimeout_info("DHCP: %s: id=%d fd=%d source=%p",
					__func__, id, timeout_source->pfd.fd,
					source);
                        g_source_remove_unix_fd(source, timeout_source->tag);
			close(timeout_source->pfd.fd);
			g_source_destroy (source);
		}
	} else {
		g_rttimeout_info("DHCP: %s: id=%d not found", __func__, id);
	}

	return source != NULL;
}
