/* event-producer.c generated by valac 0.56.19, the Vala compiler
 * generated from event-producer.vala, do not modify */

/*
 * Copyright (c) 2024-2025 focus-timer contributors
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * Authors: Kamil Prusko <kamilprusko@gmail.com>
 */

#include "ft_core.h"
#include <glib.h>
#include <string.h>
#include <stdlib.h>
#include <glib-object.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

enum  {
	FT_EVENT_PRODUCER_0_PROPERTY,
	FT_EVENT_PRODUCER_SESSION_MANAGER_PROPERTY,
	FT_EVENT_PRODUCER_TIMER_PROPERTY,
	FT_EVENT_PRODUCER_BUS_PROPERTY,
	FT_EVENT_PRODUCER_NUM_PROPERTIES
};
static GParamSpec* ft_event_producer_properties[FT_EVENT_PRODUCER_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL)))
#define _ft_event_spec_unref0(var) ((var == NULL) ? NULL : (var = (ft_event_spec_unref (var), NULL)))
#define _ft_event_free0(var) ((var == NULL) ? NULL : (var = (ft_event_free (var), NULL)))
#define _ft_context_unref0(var) ((var == NULL) ? NULL : (var = (ft_context_unref (var), NULL)))
enum  {
	FT_EVENT_PRODUCER_EVENT_SIGNAL,
	FT_EVENT_PRODUCER_NUM_SIGNALS
};
static guint ft_event_producer_signals[FT_EVENT_PRODUCER_NUM_SIGNALS] = {0};

struct _FtEventProducerPrivate {
	FtSessionManager* _session_manager;
	FtTimer* _timer;
	FtEventBus* _bus;
	FtEventSpec** event_specs;
	gint event_specs_length1;
	gint _event_specs_size_;
	GHashTable* event_spec_by_name;
	FtState previous_state;
	GQueue* queue;
	guint idle_id;
	gint64 event_source_timestamp;
	gint64 last_session_rescheduled_time;
	gboolean destroying;
	FtTrigger* timer_state_change_triggers;
	gint timer_state_change_triggers_length1;
	gint _timer_state_change_triggers_size_;
	FtTrigger* session_manager_confirm_advancement_triggers;
	gint session_manager_confirm_advancement_triggers_length1;
	gint _session_manager_confirm_advancement_triggers_size_;
	FtTrigger* session_manager_advanced_triggers;
	gint session_manager_advanced_triggers_length1;
	gint _session_manager_advanced_triggers_size_;
	FtTrigger* session_manager_notify_current_state_triggers;
	gint session_manager_notify_current_state_triggers_length1;
	gint _session_manager_notify_current_state_triggers_size_;
	FtTrigger* session_manager_session_rescheduled_triggers;
	gint session_manager_session_rescheduled_triggers_length1;
	gint _session_manager_session_rescheduled_triggers_size_;
	FtTrigger* session_manager_session_expired_triggers;
	gint session_manager_session_expired_triggers_length1;
	gint _session_manager_session_expired_triggers_size_;
};

static gint FtEventProducer_private_offset;
static gpointer ft_event_producer_parent_class = NULL;

static void ft_event_producer_event (FtEventProducer* self,
                              FtEvent* event);
static void _vala_array_add8 (FtTrigger* * array,
                       gint* length,
                       gint* size,
                       const FtTrigger* value);
static void _vala_array_add9 (FtTrigger* * array,
                       gint* length,
                       gint* size,
                       const FtTrigger* value);
static void _vala_array_add10 (FtTrigger* * array,
                        gint* length,
                        gint* size,
                        const FtTrigger* value);
static void _vala_array_add11 (FtTrigger* * array,
                        gint* length,
                        gint* size,
                        const FtTrigger* value);
static void _vala_array_add12 (FtTrigger* * array,
                        gint* length,
                        gint* size,
                        const FtTrigger* value);
static void _vala_array_add13 (FtTrigger* * array,
                        gint* length,
                        gint* size,
                        const FtTrigger* value);
static void _vala_array_add14 (FtEventSpec** * array,
                        gint* length,
                        gint* size,
                        FtEventSpec* value);
static FtEventSpec** _vala_array_dup8 (FtEventSpec** self,
                                gssize length);
static void ft_event_producer_trigger_queued_events (FtEventProducer* self,
                                              FtContext* context);
static void ft_event_producer_trigger_event (FtEventProducer* self,
                                      FtEventSpec* event_spec,
                                      gint64 timestamp);
static gboolean ft_event_producer_on_idle (FtEventProducer* self);
static void ft_event_producer_queue_event (FtEventProducer* self,
                                    FtEventSpec* event_spec);
static gboolean _ft_event_producer_on_idle_gsource_func (gpointer self);
static void ft_event_producer_on_timer_state_changed (FtEventProducer* self,
                                               const FtTimerState* current_state,
                                               const FtTimerState* previous_state);
static void ft_event_producer_on_session_manager_confirm_advancement (FtEventProducer* self,
                                                               FtTimeBlock* current_time_block,
                                                               FtTimeBlock* next_time_block);
static void ft_event_producer_on_session_manager_advanced (FtEventProducer* self,
                                                    FtSession* current_session,
                                                    FtTimeBlock* current_time_block,
                                                    FtSession* previous_session,
                                                    FtTimeBlock* previous_time_block);
static void ft_event_producer_on_session_manager_notify_current_state (FtEventProducer* self,
                                                                GObject* object,
                                                                GParamSpec* pspec);
static void ft_event_producer_on_session_manager_session_rescheduled (FtEventProducer* self,
                                                               FtSession* session,
                                                               gint64 timestamp);
static void ft_event_producer_on_session_manager_session_expired (FtEventProducer* self,
                                                           FtSession* session,
                                                           gint64 timestamp);
static void ft_event_producer_real_dispose (GObject* base);
static void _ft_event_producer_on_timer_state_changed_ft_timer_state_changed (FtTimer* _sender,
                                                                       const FtTimerState* current_state,
                                                                       const FtTimerState* previous_state,
                                                                       gpointer self);
static void _ft_event_producer_on_session_manager_confirm_advancement_ft_session_manager_confirm_advancement (FtSessionManager* _sender,
                                                                                                       FtTimeBlock* current_time_block,
                                                                                                       FtTimeBlock* next_time_block,
                                                                                                       gpointer self);
static void _ft_event_producer_on_session_manager_advanced_ft_session_manager_advanced (FtSessionManager* _sender,
                                                                                 FtSession* current_session,
                                                                                 FtTimeBlock* current_time_block,
                                                                                 FtSession* previous_session,
                                                                                 FtTimeBlock* previous_time_block,
                                                                                 gpointer self);
static void _ft_event_producer_on_session_manager_notify_current_state_g_object_notify (GObject* _sender,
                                                                                 GParamSpec* pspec,
                                                                                 gpointer self);
static void _ft_event_producer_on_session_manager_session_rescheduled_ft_session_manager_session_rescheduled (FtSessionManager* _sender,
                                                                                                       FtSession* session,
                                                                                                       gint64 timestamp,
                                                                                                       gpointer self);
static void _ft_event_producer_on_session_manager_session_expired_ft_session_manager_session_expired (FtSessionManager* _sender,
                                                                                               FtSession* session,
                                                                                               gint64 timestamp,
                                                                                               gpointer self);
static GObject * ft_event_producer_constructor (GType type,
                                         guint n_construct_properties,
                                         GObjectConstructParam * construct_properties);
static void _g_free0_ (gpointer var);
VALA_EXTERN void ft_initialize_events (FtEventProducer* producer);
static void ft_event_producer_finalize (GObject * obj);
static GType ft_event_producer_get_type_once (void);
static void _vala_ft_event_producer_get_property (GObject * object,
                                           guint property_id,
                                           GValue * value,
                                           GParamSpec * pspec);
static void _vala_ft_event_producer_set_property (GObject * object,
                                           guint property_id,
                                           const GValue * value,
                                           GParamSpec * pspec);
static void _vala_array_destroy (gpointer array,
                          gssize array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gssize array_length,
                       GDestroyNotify destroy_func);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

static GType
ft_trigger_hook_get_type_once (void)
{
	static const GEnumValue values[] = {{FT_TRIGGER_HOOK_NONE, "FT_TRIGGER_HOOK_NONE", "none"}, {FT_TRIGGER_HOOK_TIMER_STATE_CHANGED, "FT_TRIGGER_HOOK_TIMER_STATE_CHANGED", "timer-state-changed"}, {FT_TRIGGER_HOOK_SESSION_MANAGER_CONFIRM_ADVANCEMENT, "FT_TRIGGER_HOOK_SESSION_MANAGER_CONFIRM_ADVANCEMENT", "session-manager-confirm-advancement"}, {FT_TRIGGER_HOOK_SESSION_MANAGER_ADVANCED, "FT_TRIGGER_HOOK_SESSION_MANAGER_ADVANCED", "session-manager-advanced"}, {FT_TRIGGER_HOOK_SESSION_MANAGER_NOTIFY_CURRENT_STATE, "FT_TRIGGER_HOOK_SESSION_MANAGER_NOTIFY_CURRENT_STATE", "session-manager-notify-current-state"}, {FT_TRIGGER_HOOK_SESSION_MANAGER_SESSION_RESCHEDULED, "FT_TRIGGER_HOOK_SESSION_MANAGER_SESSION_RESCHEDULED", "session-manager-session-rescheduled"}, {FT_TRIGGER_HOOK_SESSION_MANAGER_SESSION_EXPIRED, "FT_TRIGGER_HOOK_SESSION_MANAGER_SESSION_EXPIRED", "session-manager-session-expired"}, {0, NULL, NULL}};
	GType ft_trigger_hook_type_id;
	ft_trigger_hook_type_id = g_enum_register_static ("FtTriggerHook", values);
	return ft_trigger_hook_type_id;
}

GType
ft_trigger_hook_get_type (void)
{
	static volatile gsize ft_trigger_hook_type_id__once = 0;
	if (g_once_init_enter (&ft_trigger_hook_type_id__once)) {
		GType ft_trigger_hook_type_id;
		ft_trigger_hook_type_id = ft_trigger_hook_get_type_once ();
		g_once_init_leave (&ft_trigger_hook_type_id__once, ft_trigger_hook_type_id);
	}
	return ft_trigger_hook_type_id__once;
}

FtTrigger*
ft_trigger_dup (const FtTrigger* self)
{
	FtTrigger* dup;
	dup = g_new0 (FtTrigger, 1);
	memcpy (dup, self, sizeof (FtTrigger));
	return dup;
}

void
ft_trigger_free (FtTrigger* self)
{
	g_free (self);
}

static GType
ft_trigger_get_type_once (void)
{
	GType ft_trigger_type_id;
	ft_trigger_type_id = g_boxed_type_register_static ("FtTrigger", (GBoxedCopyFunc) ft_trigger_dup, (GBoxedFreeFunc) ft_trigger_free);
	return ft_trigger_type_id;
}

GType
ft_trigger_get_type (void)
{
	static volatile gsize ft_trigger_type_id__once = 0;
	if (g_once_init_enter (&ft_trigger_type_id__once)) {
		GType ft_trigger_type_id;
		ft_trigger_type_id = ft_trigger_get_type_once ();
		g_once_init_leave (&ft_trigger_type_id__once, ft_trigger_type_id);
	}
	return ft_trigger_type_id__once;
}

static inline gpointer
ft_event_producer_get_instance_private (FtEventProducer* self)
{
	return G_STRUCT_MEMBER_P (self, FtEventProducer_private_offset);
}

FtEventProducer*
ft_event_producer_construct (GType object_type)
{
	FtEventProducer * self = NULL;
	FtEventBus* bus = NULL;
	FtEventBus* _tmp0_;
	FtSessionManager* _tmp1_;
	FtTimer* _tmp2_;
	_tmp0_ = ft_event_bus_new ();
	bus = _tmp0_;
	_tmp1_ = ft_session_manager_get_default ();
	_tmp2_ = ft_timer_get_default ();
	self = (FtEventProducer*) g_object_new (object_type, "session-manager", _tmp1_, "timer", _tmp2_, "bus", bus, NULL);
	_g_object_unref0 (bus);
	return self;
}

FtEventProducer*
ft_event_producer_new (void)
{
	return ft_event_producer_construct (FT_TYPE_EVENT_PRODUCER);
}

FtEventProducer*
ft_event_producer_construct_with_session_manager (GType object_type,
                                                  FtSessionManager* session_manager)
{
	FtEventProducer * self = NULL;
	FtEventBus* bus = NULL;
	FtEventBus* _tmp0_;
	FtTimer* _tmp1_;
	FtTimer* _tmp2_;
	g_return_val_if_fail (session_manager != NULL, NULL);
	_tmp0_ = ft_event_bus_new ();
	bus = _tmp0_;
	_tmp1_ = ft_session_manager_get_timer (session_manager);
	_tmp2_ = _tmp1_;
	self = (FtEventProducer*) g_object_new (object_type, "session-manager", session_manager, "timer", _tmp2_, "bus", bus, NULL);
	_g_object_unref0 (bus);
	return self;
}

FtEventProducer*
ft_event_producer_new_with_session_manager (FtSessionManager* session_manager)
{
	return ft_event_producer_construct_with_session_manager (FT_TYPE_EVENT_PRODUCER, session_manager);
}

static void
_vala_array_add8 (FtTrigger* * array,
                  gint* length,
                  gint* size,
                  const FtTrigger* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (FtTrigger, *array, *size);
	}
	(*array)[(*length)++] = *value;
}

static void
_vala_array_add9 (FtTrigger* * array,
                  gint* length,
                  gint* size,
                  const FtTrigger* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (FtTrigger, *array, *size);
	}
	(*array)[(*length)++] = *value;
}

static void
_vala_array_add10 (FtTrigger* * array,
                   gint* length,
                   gint* size,
                   const FtTrigger* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (FtTrigger, *array, *size);
	}
	(*array)[(*length)++] = *value;
}

static void
_vala_array_add11 (FtTrigger* * array,
                   gint* length,
                   gint* size,
                   const FtTrigger* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (FtTrigger, *array, *size);
	}
	(*array)[(*length)++] = *value;
}

static void
_vala_array_add12 (FtTrigger* * array,
                   gint* length,
                   gint* size,
                   const FtTrigger* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (FtTrigger, *array, *size);
	}
	(*array)[(*length)++] = *value;
}

static void
_vala_array_add13 (FtTrigger* * array,
                   gint* length,
                   gint* size,
                   const FtTrigger* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (FtTrigger, *array, *size);
	}
	(*array)[(*length)++] = *value;
}

static gpointer
_ft_event_spec_ref0 (gpointer self)
{
	return self ? ft_event_spec_ref (self) : NULL;
}

static void
_vala_array_add14 (FtEventSpec** * array,
                   gint* length,
                   gint* size,
                   FtEventSpec* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (FtEventSpec*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}

void
ft_event_producer_install_event (FtEventProducer* self,
                                 FtEventSpec* event_spec)
{
	FtEventSpec* unowned_event_spec = NULL;
	FtTrigger* _tmp0_;
	gint _tmp0__length1;
	GHashTable* _tmp8_;
	const gchar* _tmp9_;
	gchar* _tmp10_;
	FtEventSpec* _tmp11_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (event_spec != NULL);
	unowned_event_spec = event_spec;
	_tmp0_ = event_spec->triggers;
	_tmp0__length1 = event_spec->triggers_length1;
	{
		FtTrigger* trigger_collection = NULL;
		gint trigger_collection_length1 = 0;
		gint _trigger_collection_size_ = 0;
		gint trigger_it = 0;
		trigger_collection = _tmp0_;
		trigger_collection_length1 = _tmp0__length1;
		for (trigger_it = 0; trigger_it < trigger_collection_length1; trigger_it = trigger_it + 1) {
			FtTrigger trigger = {0};
			trigger = trigger_collection[trigger_it];
			{
				FtTrigger _tmp1_;
				_tmp1_ = trigger;
				switch (_tmp1_.hook) {
					case FT_TRIGGER_HOOK_TIMER_STATE_CHANGED:
					{
						FtTrigger _tmp2_;
						_tmp2_ = trigger;
						_vala_array_add8 (&self->priv->timer_state_change_triggers, &self->priv->timer_state_change_triggers_length1, &self->priv->_timer_state_change_triggers_size_, &_tmp2_);
						break;
					}
					case FT_TRIGGER_HOOK_SESSION_MANAGER_CONFIRM_ADVANCEMENT:
					{
						FtTrigger _tmp3_;
						_tmp3_ = trigger;
						_vala_array_add9 (&self->priv->session_manager_confirm_advancement_triggers, &self->priv->session_manager_confirm_advancement_triggers_length1, &self->priv->_session_manager_confirm_advancement_triggers_size_, &_tmp3_);
						break;
					}
					case FT_TRIGGER_HOOK_SESSION_MANAGER_ADVANCED:
					{
						FtTrigger _tmp4_;
						_tmp4_ = trigger;
						_vala_array_add10 (&self->priv->session_manager_advanced_triggers, &self->priv->session_manager_advanced_triggers_length1, &self->priv->_session_manager_advanced_triggers_size_, &_tmp4_);
						break;
					}
					case FT_TRIGGER_HOOK_SESSION_MANAGER_NOTIFY_CURRENT_STATE:
					{
						FtTrigger _tmp5_;
						_tmp5_ = trigger;
						_vala_array_add11 (&self->priv->session_manager_notify_current_state_triggers, &self->priv->session_manager_notify_current_state_triggers_length1, &self->priv->_session_manager_notify_current_state_triggers_size_, &_tmp5_);
						break;
					}
					case FT_TRIGGER_HOOK_SESSION_MANAGER_SESSION_RESCHEDULED:
					{
						FtTrigger _tmp6_;
						_tmp6_ = trigger;
						_vala_array_add12 (&self->priv->session_manager_session_rescheduled_triggers, &self->priv->session_manager_session_rescheduled_triggers_length1, &self->priv->_session_manager_session_rescheduled_triggers_size_, &_tmp6_);
						break;
					}
					case FT_TRIGGER_HOOK_SESSION_MANAGER_SESSION_EXPIRED:
					{
						FtTrigger _tmp7_;
						_tmp7_ = trigger;
						_vala_array_add13 (&self->priv->session_manager_session_expired_triggers, &self->priv->session_manager_session_expired_triggers_length1, &self->priv->_session_manager_session_expired_triggers_size_, &_tmp7_);
						break;
					}
					default:
					{
						g_assert_not_reached ();
					}
				}
			}
		}
	}
	_tmp8_ = self->priv->event_spec_by_name;
	_tmp9_ = event_spec->name;
	_tmp10_ = g_strdup (_tmp9_);
	_tmp11_ = unowned_event_spec;
	if (g_hash_table_insert (_tmp8_, _tmp10_, _tmp11_)) {
		FtEventSpec* _tmp12_;
		_tmp12_ = _ft_event_spec_ref0 (event_spec);
		_vala_array_add14 (&self->priv->event_specs, &self->priv->event_specs_length1, &self->priv->_event_specs_size_, _tmp12_);
	} else {
		const gchar* _tmp13_;
		_tmp13_ = event_spec->name;
		g_error ("event-producer.vala:214: Unable to install event '%s'", _tmp13_);
	}
}

FtEventSpec*
ft_event_producer_find_event (FtEventProducer* self,
                              const gchar* event_name)
{
	GHashTable* _tmp0_;
	gconstpointer _tmp1_;
	FtEventSpec* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (event_name != NULL, NULL);
	_tmp0_ = self->priv->event_spec_by_name;
	_tmp1_ = g_hash_table_lookup (_tmp0_, event_name);
	result = (FtEventSpec*) _tmp1_;
	return result;
}

static FtEventSpec**
_vala_array_dup8 (FtEventSpec** self,
                  gssize length)
{
	if (length > 0) {
		return _vala_memdup2 (self, length * sizeof (FtEventSpec*));
	}
	return NULL;
}

FtEventSpec**
ft_event_producer_list_events (FtEventProducer* self,
                               gint* result_length1)
{
	FtEventSpec** _tmp0_;
	gint _tmp0__length1;
	FtEventSpec** _tmp1_;
	gint _tmp1__length1;
	FtEventSpec** _tmp2_;
	gint _tmp2__length1;
	FtEventSpec** result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->event_specs;
	_tmp0__length1 = self->priv->event_specs_length1;
	_tmp1_ = (_tmp0_ != NULL) ? _vala_array_dup8 (_tmp0_, _tmp0__length1) : _tmp0_;
	_tmp1__length1 = _tmp0__length1;
	_tmp2_ = _tmp1_;
	_tmp2__length1 = _tmp1__length1;
	if (result_length1) {
		*result_length1 = _tmp2__length1;
	}
	result = _tmp2_;
	return result;
}

static void
ft_event_producer_trigger_queued_events (FtEventProducer* self,
                                         FtContext* context)
{
	FtEventSpec* event_spec = NULL;
	g_return_if_fail (self != NULL);
	g_return_if_fail (context != NULL);
	if (self->priv->idle_id != ((guint) 0)) {
		g_source_remove (self->priv->idle_id);
		self->priv->idle_id = (guint) 0;
	}
	while (TRUE) {
		GQueue* _tmp0_;
		gpointer _tmp1_;
		FtEventSpec* _tmp2_;
		FtEventSpec* _tmp3_;
		FtEventSpec* _tmp4_;
		FtEvent* _tmp5_;
		FtEvent* _tmp6_;
		_tmp0_ = self->priv->queue;
		_tmp1_ = g_queue_pop_head (_tmp0_);
		_tmp2_ = _ft_event_spec_ref0 ((FtEventSpec*) _tmp1_);
		_ft_event_spec_unref0 (event_spec);
		event_spec = _tmp2_;
		_tmp3_ = event_spec;
		if (!(_tmp3_ != NULL)) {
			break;
		}
		_tmp4_ = event_spec;
		_tmp5_ = ft_event_new (_tmp4_, context);
		_tmp6_ = _tmp5_;
		g_signal_emit (self, ft_event_producer_signals[FT_EVENT_PRODUCER_EVENT_SIGNAL], 0, _tmp6_);
		_ft_event_free0 (_tmp6_);
	}
	_ft_event_spec_unref0 (event_spec);
}

static void
ft_event_producer_trigger_event (FtEventProducer* self,
                                 FtEventSpec* event_spec,
                                 gint64 timestamp)
{
	FtContext* context = NULL;
	FtContext* _tmp0_;
	FtContext* _tmp1_;
	FtContext* _tmp2_;
	FtEvent* _tmp3_;
	FtEvent* _tmp4_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (event_spec != NULL);
	if (self->priv->destroying) {
		return;
	}
	_tmp0_ = ft_context_new_build (timestamp);
	context = _tmp0_;
	_tmp1_ = context;
	ft_event_producer_trigger_queued_events (self, _tmp1_);
	_tmp2_ = context;
	_tmp3_ = ft_event_new (event_spec, _tmp2_);
	_tmp4_ = _tmp3_;
	g_signal_emit (self, ft_event_producer_signals[FT_EVENT_PRODUCER_EVENT_SIGNAL], 0, _tmp4_);
	_ft_event_free0 (_tmp4_);
	_ft_context_unref0 (context);
}

static gboolean
ft_event_producer_on_idle (FtEventProducer* self)
{
	gint64 timestamp = 0LL;
	FtContext* _tmp2_;
	FtContext* _tmp3_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	timestamp = self->priv->event_source_timestamp;
	if (ft_timestamp_is_undefined (timestamp)) {
		FtTimer* _tmp0_;
		FtTimer* _tmp1_;
		_tmp0_ = self->priv->_timer;
		_tmp1_ = self->priv->_timer;
		timestamp = MAX (ft_timer_get_last_state_changed_time (_tmp0_), ft_timer_get_last_tick_time (_tmp1_));
	}
	self->priv->idle_id = (guint) 0;
	self->priv->event_source_timestamp = FT_TIMESTAMP_UNDEFINED;
	_tmp2_ = ft_context_new_build (timestamp);
	_tmp3_ = _tmp2_;
	ft_event_producer_trigger_queued_events (self, _tmp3_);
	_ft_context_unref0 (_tmp3_);
	result = G_SOURCE_REMOVE;
	return result;
}

static gboolean
_ft_event_producer_on_idle_gsource_func (gpointer self)
{
	gboolean result;
	result = ft_event_producer_on_idle ((FtEventProducer*) self);
	return result;
}

static void
ft_event_producer_queue_event (FtEventProducer* self,
                               FtEventSpec* event_spec)
{
	GQueue* _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (event_spec != NULL);
	if (self->priv->destroying) {
		return;
	}
	_tmp0_ = self->priv->queue;
	g_queue_push_tail (_tmp0_, event_spec);
	self->priv->event_source_timestamp = ft_context_get_event_source_timestamp ();
	if (self->priv->idle_id == ((guint) 0)) {
		self->priv->idle_id = g_idle_add_full (G_PRIORITY_DEFAULT, _ft_event_producer_on_idle_gsource_func, g_object_ref (self), g_object_unref);
		g_source_set_name_by_id (self->priv->idle_id, "Ft.EventProducer.trigger_queued_events");
	}
}

static void
ft_event_producer_on_timer_state_changed (FtEventProducer* self,
                                          const FtTimerState* current_state,
                                          const FtTimerState* previous_state)
{
	gint64 timestamp = 0LL;
	FtTimer* _tmp0_;
	FtTrigger* _tmp1_;
	gint _tmp1__length1;
	g_return_if_fail (self != NULL);
	g_return_if_fail (current_state != NULL);
	g_return_if_fail (previous_state != NULL);
	_tmp0_ = self->priv->_timer;
	timestamp = ft_timer_get_last_state_changed_time (_tmp0_);
	_tmp1_ = self->priv->timer_state_change_triggers;
	_tmp1__length1 = self->priv->timer_state_change_triggers_length1;
	{
		FtTrigger* trigger_collection = NULL;
		gint trigger_collection_length1 = 0;
		gint _trigger_collection_size_ = 0;
		gint trigger_it = 0;
		trigger_collection = _tmp1_;
		trigger_collection_length1 = _tmp1__length1;
		for (trigger_it = 0; trigger_it < trigger_collection_length1; trigger_it = trigger_it + 1) {
			FtTrigger trigger = {0};
			trigger = trigger_collection[trigger_it];
			{
				FtTimerStateChangedTriggerFunc trigger_func = NULL;
				FtTrigger _tmp2_;
				FtTriggerFunc _tmp3_;
				FtTimerStateChangedTriggerFunc _tmp4_;
				FtTimerState _tmp5_;
				FtTimerState _tmp6_;
				_tmp2_ = trigger;
				_tmp3_ = _tmp2_.func;
				trigger_func = (FtTimerStateChangedTriggerFunc) _tmp3_;
				_tmp4_ = trigger_func;
				_tmp5_ = *current_state;
				_tmp6_ = *previous_state;
				if (_tmp4_ (&_tmp5_, &_tmp6_)) {
					FtTrigger _tmp7_;
					FtEventSpec* _tmp8_;
					_tmp7_ = trigger;
					_tmp8_ = _tmp7_.event_spec;
					ft_event_producer_trigger_event (self, _tmp8_, timestamp);
				}
			}
		}
	}
}

static void
ft_event_producer_on_session_manager_confirm_advancement (FtEventProducer* self,
                                                          FtTimeBlock* current_time_block,
                                                          FtTimeBlock* next_time_block)
{
	gint64 timestamp = 0LL;
	gint64 _tmp0_;
	gint64 _tmp1_;
	FtTrigger* _tmp2_;
	gint _tmp2__length1;
	g_return_if_fail (self != NULL);
	g_return_if_fail (current_time_block != NULL);
	g_return_if_fail (next_time_block != NULL);
	_tmp0_ = ft_schedulable_get_end_time ((FtSchedulable*) current_time_block);
	_tmp1_ = _tmp0_;
	timestamp = _tmp1_;
	_tmp2_ = self->priv->session_manager_confirm_advancement_triggers;
	_tmp2__length1 = self->priv->session_manager_confirm_advancement_triggers_length1;
	{
		FtTrigger* trigger_collection = NULL;
		gint trigger_collection_length1 = 0;
		gint _trigger_collection_size_ = 0;
		gint trigger_it = 0;
		trigger_collection = _tmp2_;
		trigger_collection_length1 = _tmp2__length1;
		for (trigger_it = 0; trigger_it < trigger_collection_length1; trigger_it = trigger_it + 1) {
			FtTrigger trigger = {0};
			trigger = trigger_collection[trigger_it];
			{
				FtSessionManagerConfirmAdvancementTriggerFunc trigger_func = NULL;
				FtTrigger _tmp3_;
				FtTriggerFunc _tmp4_;
				FtSessionManagerConfirmAdvancementTriggerFunc _tmp5_;
				_tmp3_ = trigger;
				_tmp4_ = _tmp3_.func;
				trigger_func = (FtSessionManagerConfirmAdvancementTriggerFunc) _tmp4_;
				_tmp5_ = trigger_func;
				if (_tmp5_ (current_time_block, next_time_block)) {
					FtTrigger _tmp6_;
					FtEventSpec* _tmp7_;
					_tmp6_ = trigger;
					_tmp7_ = _tmp6_.event_spec;
					ft_event_producer_trigger_event (self, _tmp7_, timestamp);
				}
			}
		}
	}
}

static void
ft_event_producer_on_session_manager_advanced (FtEventProducer* self,
                                               FtSession* current_session,
                                               FtTimeBlock* current_time_block,
                                               FtSession* previous_session,
                                               FtTimeBlock* previous_time_block)
{
	gint64 timestamp = 0LL;
	FtTimer* _tmp0_;
	FtTrigger* _tmp5_;
	gint _tmp5__length1;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_timer;
	timestamp = ft_timer_get_last_state_changed_time (_tmp0_);
	if (previous_time_block != NULL) {
		gint64 _tmp1_;
		gint64 _tmp2_;
		_tmp1_ = ft_schedulable_get_end_time ((FtSchedulable*) previous_time_block);
		_tmp2_ = _tmp1_;
		timestamp = _tmp2_;
	}
	if (current_time_block != NULL) {
		gint64 _tmp3_;
		gint64 _tmp4_;
		_tmp3_ = ft_schedulable_get_start_time ((FtSchedulable*) current_time_block);
		_tmp4_ = _tmp3_;
		timestamp = _tmp4_;
	}
	_tmp5_ = self->priv->session_manager_advanced_triggers;
	_tmp5__length1 = self->priv->session_manager_advanced_triggers_length1;
	{
		FtTrigger* trigger_collection = NULL;
		gint trigger_collection_length1 = 0;
		gint _trigger_collection_size_ = 0;
		gint trigger_it = 0;
		trigger_collection = _tmp5_;
		trigger_collection_length1 = _tmp5__length1;
		for (trigger_it = 0; trigger_it < trigger_collection_length1; trigger_it = trigger_it + 1) {
			FtTrigger trigger = {0};
			trigger = trigger_collection[trigger_it];
			{
				FtSessionManagerAdvancedTriggerFunc trigger_func = NULL;
				FtTrigger _tmp6_;
				FtTriggerFunc _tmp7_;
				FtSessionManagerAdvancedTriggerFunc _tmp8_;
				_tmp6_ = trigger;
				_tmp7_ = _tmp6_.func;
				trigger_func = (FtSessionManagerAdvancedTriggerFunc) _tmp7_;
				_tmp8_ = trigger_func;
				if (_tmp8_ (current_session, current_time_block, previous_session, previous_time_block)) {
					FtTrigger _tmp9_;
					FtEventSpec* _tmp10_;
					_tmp9_ = trigger;
					_tmp10_ = _tmp9_.event_spec;
					ft_event_producer_trigger_event (self, _tmp10_, timestamp);
				}
			}
		}
	}
}

static void
ft_event_producer_on_session_manager_notify_current_state (FtEventProducer* self,
                                                           GObject* object,
                                                           GParamSpec* pspec)
{
	FtState current_state = 0;
	FtSessionManager* _tmp0_;
	FtState _tmp1_;
	FtState _tmp2_;
	FtState previous_state = 0;
	FtTrigger* _tmp3_;
	gint _tmp3__length1;
	g_return_if_fail (self != NULL);
	g_return_if_fail (object != NULL);
	g_return_if_fail (pspec != NULL);
	_tmp0_ = self->priv->_session_manager;
	_tmp1_ = ft_session_manager_get_current_state (_tmp0_);
	_tmp2_ = _tmp1_;
	current_state = _tmp2_;
	previous_state = self->priv->previous_state;
	if (current_state == previous_state) {
		return;
	}
	self->priv->previous_state = current_state;
	_tmp3_ = self->priv->session_manager_notify_current_state_triggers;
	_tmp3__length1 = self->priv->session_manager_notify_current_state_triggers_length1;
	{
		FtTrigger* trigger_collection = NULL;
		gint trigger_collection_length1 = 0;
		gint _trigger_collection_size_ = 0;
		gint trigger_it = 0;
		trigger_collection = _tmp3_;
		trigger_collection_length1 = _tmp3__length1;
		for (trigger_it = 0; trigger_it < trigger_collection_length1; trigger_it = trigger_it + 1) {
			FtTrigger trigger = {0};
			trigger = trigger_collection[trigger_it];
			{
				FtSessionManagerNotifyCurrentStateTriggerFunc trigger_func = NULL;
				FtTrigger _tmp4_;
				FtTriggerFunc _tmp5_;
				FtSessionManagerNotifyCurrentStateTriggerFunc _tmp6_;
				_tmp4_ = trigger;
				_tmp5_ = _tmp4_.func;
				trigger_func = (FtSessionManagerNotifyCurrentStateTriggerFunc) _tmp5_;
				_tmp6_ = trigger_func;
				if (_tmp6_ (current_state, previous_state)) {
					FtTrigger _tmp7_;
					FtEventSpec* _tmp8_;
					_tmp7_ = trigger;
					_tmp8_ = _tmp7_.event_spec;
					ft_event_producer_queue_event (self, _tmp8_);
				}
			}
		}
	}
}

static void
ft_event_producer_on_session_manager_session_rescheduled (FtEventProducer* self,
                                                          FtSession* session,
                                                          gint64 timestamp)
{
	FtTrigger* _tmp0_;
	gint _tmp0__length1;
	g_return_if_fail (self != NULL);
	g_return_if_fail (session != NULL);
	if (timestamp == self->priv->last_session_rescheduled_time) {
		g_debug ("event-producer.vala:375: Detected duplicate 'session-rescheduled' even" \
"t. Dropping...");
		return;
	}
	self->priv->last_session_rescheduled_time = timestamp;
	_tmp0_ = self->priv->session_manager_session_rescheduled_triggers;
	_tmp0__length1 = self->priv->session_manager_session_rescheduled_triggers_length1;
	{
		FtTrigger* trigger_collection = NULL;
		gint trigger_collection_length1 = 0;
		gint _trigger_collection_size_ = 0;
		gint trigger_it = 0;
		trigger_collection = _tmp0_;
		trigger_collection_length1 = _tmp0__length1;
		for (trigger_it = 0; trigger_it < trigger_collection_length1; trigger_it = trigger_it + 1) {
			FtTrigger trigger = {0};
			trigger = trigger_collection[trigger_it];
			{
				FtSessionManagerSessionRescheduledTriggerFunc trigger_func = NULL;
				FtTrigger _tmp1_;
				FtTriggerFunc _tmp2_;
				FtSessionManagerSessionRescheduledTriggerFunc _tmp3_;
				_tmp1_ = trigger;
				_tmp2_ = _tmp1_.func;
				trigger_func = (FtSessionManagerSessionRescheduledTriggerFunc) _tmp2_;
				_tmp3_ = trigger_func;
				if (_tmp3_ (session)) {
					FtTrigger _tmp4_;
					FtEventSpec* _tmp5_;
					_tmp4_ = trigger;
					_tmp5_ = _tmp4_.event_spec;
					ft_event_producer_queue_event (self, _tmp5_);
				}
			}
		}
	}
}

static void
ft_event_producer_on_session_manager_session_expired (FtEventProducer* self,
                                                      FtSession* session,
                                                      gint64 timestamp)
{
	FtTrigger* _tmp0_;
	gint _tmp0__length1;
	g_return_if_fail (self != NULL);
	g_return_if_fail (session != NULL);
	_tmp0_ = self->priv->session_manager_session_expired_triggers;
	_tmp0__length1 = self->priv->session_manager_session_expired_triggers_length1;
	{
		FtTrigger* trigger_collection = NULL;
		gint trigger_collection_length1 = 0;
		gint _trigger_collection_size_ = 0;
		gint trigger_it = 0;
		trigger_collection = _tmp0_;
		trigger_collection_length1 = _tmp0__length1;
		for (trigger_it = 0; trigger_it < trigger_collection_length1; trigger_it = trigger_it + 1) {
			FtTrigger trigger = {0};
			trigger = trigger_collection[trigger_it];
			{
				FtSessionManagerSessionExpiredTriggerFunc trigger_func = NULL;
				FtTrigger _tmp1_;
				FtTriggerFunc _tmp2_;
				FtSessionManagerSessionExpiredTriggerFunc _tmp3_;
				_tmp1_ = trigger;
				_tmp2_ = _tmp1_.func;
				trigger_func = (FtSessionManagerSessionExpiredTriggerFunc) _tmp2_;
				_tmp3_ = trigger_func;
				if (_tmp3_ (session)) {
					FtTrigger _tmp4_;
					FtEventSpec* _tmp5_;
					_tmp4_ = trigger;
					_tmp5_ = _tmp4_.event_spec;
					ft_event_producer_trigger_event (self, _tmp5_, timestamp);
				}
			}
		}
	}
}

void
ft_event_producer_flush (FtEventProducer* self)
{
	FtContext* _tmp0_;
	FtContext* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = ft_context_new_build (FT_TIMESTAMP_UNDEFINED);
	_tmp1_ = _tmp0_;
	ft_event_producer_trigger_queued_events (self, _tmp1_);
	_ft_context_unref0 (_tmp1_);
}

void
ft_event_producer_destroy (FtEventProducer* self)
{
	FtContext* _tmp0_;
	FtContext* _tmp1_;
	g_return_if_fail (self != NULL);
	self->priv->destroying = TRUE;
	_tmp0_ = ft_context_new_build (FT_TIMESTAMP_UNDEFINED);
	_tmp1_ = _tmp0_;
	ft_event_producer_trigger_queued_events (self, _tmp1_);
	_ft_context_unref0 (_tmp1_);
}

static void
_ft_event_producer_on_timer_state_changed_ft_timer_state_changed (FtTimer* _sender,
                                                                  const FtTimerState* current_state,
                                                                  const FtTimerState* previous_state,
                                                                  gpointer self)
{
	ft_event_producer_on_timer_state_changed ((FtEventProducer*) self, current_state, previous_state);
}

static void
_ft_event_producer_on_session_manager_confirm_advancement_ft_session_manager_confirm_advancement (FtSessionManager* _sender,
                                                                                                  FtTimeBlock* current_time_block,
                                                                                                  FtTimeBlock* next_time_block,
                                                                                                  gpointer self)
{
	ft_event_producer_on_session_manager_confirm_advancement ((FtEventProducer*) self, current_time_block, next_time_block);
}

static void
_ft_event_producer_on_session_manager_advanced_ft_session_manager_advanced (FtSessionManager* _sender,
                                                                            FtSession* current_session,
                                                                            FtTimeBlock* current_time_block,
                                                                            FtSession* previous_session,
                                                                            FtTimeBlock* previous_time_block,
                                                                            gpointer self)
{
	ft_event_producer_on_session_manager_advanced ((FtEventProducer*) self, current_session, current_time_block, previous_session, previous_time_block);
}

static void
_ft_event_producer_on_session_manager_notify_current_state_g_object_notify (GObject* _sender,
                                                                            GParamSpec* pspec,
                                                                            gpointer self)
{
	ft_event_producer_on_session_manager_notify_current_state ((FtEventProducer*) self, _sender, pspec);
}

static void
_ft_event_producer_on_session_manager_session_rescheduled_ft_session_manager_session_rescheduled (FtSessionManager* _sender,
                                                                                                  FtSession* session,
                                                                                                  gint64 timestamp,
                                                                                                  gpointer self)
{
	ft_event_producer_on_session_manager_session_rescheduled ((FtEventProducer*) self, session, timestamp);
}

static void
_ft_event_producer_on_session_manager_session_expired_ft_session_manager_session_expired (FtSessionManager* _sender,
                                                                                          FtSession* session,
                                                                                          gint64 timestamp,
                                                                                          gpointer self)
{
	ft_event_producer_on_session_manager_session_expired ((FtEventProducer*) self, session, timestamp);
}

static void
ft_event_producer_real_dispose (GObject* base)
{
	FtEventProducer * self;
	GHashTable* _tmp0_;
	FtTimer* _tmp2_;
	FtSessionManager* _tmp5_;
	self = (FtEventProducer*) base;
	if (self->priv->idle_id != ((guint) 0)) {
		g_source_remove (self->priv->idle_id);
		self->priv->idle_id = (guint) 0;
	}
	_tmp0_ = self->priv->event_spec_by_name;
	if (_tmp0_ != NULL) {
		GHashTable* _tmp1_;
		_tmp1_ = self->priv->event_spec_by_name;
		g_hash_table_remove_all (_tmp1_);
	}
	_tmp2_ = self->priv->_timer;
	if (_tmp2_ != NULL) {
		FtTimer* _tmp3_;
		guint _tmp4_;
		_tmp3_ = self->priv->_timer;
		g_signal_parse_name ("state-changed", FT_TYPE_TIMER, &_tmp4_, NULL, FALSE);
		g_signal_handlers_disconnect_matched (_tmp3_, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp4_, 0, NULL, (GCallback) _ft_event_producer_on_timer_state_changed_ft_timer_state_changed, self);
		_g_object_unref0 (self->priv->_timer);
		self->priv->_timer = NULL;
	}
	_tmp5_ = self->priv->_session_manager;
	if (_tmp5_ != NULL) {
		FtSessionManager* _tmp6_;
		guint _tmp7_;
		FtSessionManager* _tmp8_;
		guint _tmp9_;
		FtSessionManager* _tmp10_;
		guint _tmp11_;
		GQuark _tmp12_;
		FtSessionManager* _tmp13_;
		guint _tmp14_;
		FtSessionManager* _tmp15_;
		guint _tmp16_;
		_tmp6_ = self->priv->_session_manager;
		g_signal_parse_name ("confirm-advancement", FT_TYPE_SESSION_MANAGER, &_tmp7_, NULL, FALSE);
		g_signal_handlers_disconnect_matched (_tmp6_, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp7_, 0, NULL, (GCallback) _ft_event_producer_on_session_manager_confirm_advancement_ft_session_manager_confirm_advancement, self);
		_tmp8_ = self->priv->_session_manager;
		g_signal_parse_name ("advanced", FT_TYPE_SESSION_MANAGER, &_tmp9_, NULL, FALSE);
		g_signal_handlers_disconnect_matched (_tmp8_, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp9_, 0, NULL, (GCallback) _ft_event_producer_on_session_manager_advanced_ft_session_manager_advanced, self);
		_tmp10_ = self->priv->_session_manager;
		g_signal_parse_name ("notify::current-state", G_TYPE_OBJECT, &_tmp11_, &_tmp12_, TRUE);
		g_signal_handlers_disconnect_matched ((GObject*) _tmp10_, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp11_, _tmp12_, NULL, (GCallback) _ft_event_producer_on_session_manager_notify_current_state_g_object_notify, self);
		_tmp13_ = self->priv->_session_manager;
		g_signal_parse_name ("session-rescheduled", FT_TYPE_SESSION_MANAGER, &_tmp14_, NULL, FALSE);
		g_signal_handlers_disconnect_matched (_tmp13_, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp14_, 0, NULL, (GCallback) _ft_event_producer_on_session_manager_session_rescheduled_ft_session_manager_session_rescheduled, self);
		_tmp15_ = self->priv->_session_manager;
		g_signal_parse_name ("session-expired", FT_TYPE_SESSION_MANAGER, &_tmp16_, NULL, FALSE);
		g_signal_handlers_disconnect_matched (_tmp15_, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp16_, 0, NULL, (GCallback) _ft_event_producer_on_session_manager_session_expired_ft_session_manager_session_expired, self);
		_g_object_unref0 (self->priv->_session_manager);
		self->priv->_session_manager = NULL;
	}
	_g_object_unref0 (self->priv->_bus);
	self->priv->_bus = NULL;
	self->priv->event_specs = (_vala_array_free (self->priv->event_specs, self->priv->event_specs_length1, (GDestroyNotify) ft_event_spec_unref), NULL);
	self->priv->event_specs = NULL;
	self->priv->event_specs_length1 = 0;
	self->priv->_event_specs_size_ = self->priv->event_specs_length1;
	_g_hash_table_unref0 (self->priv->event_spec_by_name);
	self->priv->event_spec_by_name = NULL;
	(self->priv->queue == NULL) ? NULL : (self->priv->queue = (g_queue_free (self->priv->queue), NULL));
	self->priv->queue = NULL;
	self->priv->event_source_timestamp = FT_TIMESTAMP_UNDEFINED;
	self->priv->timer_state_change_triggers = (g_free (self->priv->timer_state_change_triggers), NULL);
	self->priv->timer_state_change_triggers = NULL;
	self->priv->timer_state_change_triggers_length1 = 0;
	self->priv->_timer_state_change_triggers_size_ = self->priv->timer_state_change_triggers_length1;
	self->priv->session_manager_confirm_advancement_triggers = (g_free (self->priv->session_manager_confirm_advancement_triggers), NULL);
	self->priv->session_manager_confirm_advancement_triggers = NULL;
	self->priv->session_manager_confirm_advancement_triggers_length1 = 0;
	self->priv->_session_manager_confirm_advancement_triggers_size_ = self->priv->session_manager_confirm_advancement_triggers_length1;
	self->priv->session_manager_advanced_triggers = (g_free (self->priv->session_manager_advanced_triggers), NULL);
	self->priv->session_manager_advanced_triggers = NULL;
	self->priv->session_manager_advanced_triggers_length1 = 0;
	self->priv->_session_manager_advanced_triggers_size_ = self->priv->session_manager_advanced_triggers_length1;
	self->priv->session_manager_notify_current_state_triggers = (g_free (self->priv->session_manager_notify_current_state_triggers), NULL);
	self->priv->session_manager_notify_current_state_triggers = NULL;
	self->priv->session_manager_notify_current_state_triggers_length1 = 0;
	self->priv->_session_manager_notify_current_state_triggers_size_ = self->priv->session_manager_notify_current_state_triggers_length1;
	self->priv->session_manager_session_rescheduled_triggers = (g_free (self->priv->session_manager_session_rescheduled_triggers), NULL);
	self->priv->session_manager_session_rescheduled_triggers = NULL;
	self->priv->session_manager_session_rescheduled_triggers_length1 = 0;
	self->priv->_session_manager_session_rescheduled_triggers_size_ = self->priv->session_manager_session_rescheduled_triggers_length1;
	self->priv->session_manager_session_expired_triggers = (g_free (self->priv->session_manager_session_expired_triggers), NULL);
	self->priv->session_manager_session_expired_triggers = NULL;
	self->priv->session_manager_session_expired_triggers_length1 = 0;
	self->priv->_session_manager_session_expired_triggers_size_ = self->priv->session_manager_session_expired_triggers_length1;
	G_OBJECT_CLASS (ft_event_producer_parent_class)->dispose (G_TYPE_CHECK_INSTANCE_CAST (self, G_TYPE_OBJECT, GObject));
}

FtSessionManager*
ft_event_producer_get_session_manager (FtEventProducer* self)
{
	FtSessionManager* result;
	FtSessionManager* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_session_manager;
	result = _tmp0_;
	return result;
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static void
ft_event_producer_set_session_manager (FtEventProducer* self,
                                       FtSessionManager* value)
{
	FtSessionManager* _tmp0_;
	FtSessionManager* _tmp1_;
	FtSessionManager* _tmp2_;
	FtSessionManager* _tmp3_;
	FtSessionManager* _tmp4_;
	FtSessionManager* _tmp5_;
	FtSessionManager* _tmp6_;
	FtState _tmp7_;
	FtState _tmp8_;
	g_return_if_fail (self != NULL);
	_tmp0_ = _g_object_ref0 (value);
	_g_object_unref0 (self->priv->_session_manager);
	self->priv->_session_manager = _tmp0_;
	_tmp1_ = self->priv->_session_manager;
	g_signal_connect_object (_tmp1_, "confirm-advancement", (GCallback) _ft_event_producer_on_session_manager_confirm_advancement_ft_session_manager_confirm_advancement, self, 0);
	_tmp2_ = self->priv->_session_manager;
	g_signal_connect_object (_tmp2_, "advanced", (GCallback) _ft_event_producer_on_session_manager_advanced_ft_session_manager_advanced, self, 0);
	_tmp3_ = self->priv->_session_manager;
	g_signal_connect_object ((GObject*) _tmp3_, "notify::current-state", (GCallback) _ft_event_producer_on_session_manager_notify_current_state_g_object_notify, self, 0);
	_tmp4_ = self->priv->_session_manager;
	g_signal_connect_object (_tmp4_, "session-rescheduled", (GCallback) _ft_event_producer_on_session_manager_session_rescheduled_ft_session_manager_session_rescheduled, self, 0);
	_tmp5_ = self->priv->_session_manager;
	g_signal_connect_object (_tmp5_, "session-expired", (GCallback) _ft_event_producer_on_session_manager_session_expired_ft_session_manager_session_expired, self, 0);
	_tmp6_ = self->priv->_session_manager;
	_tmp7_ = ft_session_manager_get_current_state (_tmp6_);
	_tmp8_ = _tmp7_;
	self->priv->previous_state = _tmp8_;
	g_object_notify_by_pspec ((GObject *) self, ft_event_producer_properties[FT_EVENT_PRODUCER_SESSION_MANAGER_PROPERTY]);
}

FtTimer*
ft_event_producer_get_timer (FtEventProducer* self)
{
	FtTimer* result;
	FtTimer* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_timer;
	result = _tmp0_;
	return result;
}

static void
ft_event_producer_set_timer (FtEventProducer* self,
                             FtTimer* value)
{
	FtTimer* _tmp0_;
	FtTimer* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = _g_object_ref0 (value);
	_g_object_unref0 (self->priv->_timer);
	self->priv->_timer = _tmp0_;
	_tmp1_ = self->priv->_timer;
	g_signal_connect_object (_tmp1_, "state-changed", (GCallback) _ft_event_producer_on_timer_state_changed_ft_timer_state_changed, self, 0);
	g_object_notify_by_pspec ((GObject *) self, ft_event_producer_properties[FT_EVENT_PRODUCER_TIMER_PROPERTY]);
}

FtEventBus*
ft_event_producer_get_bus (FtEventProducer* self)
{
	FtEventBus* result;
	FtEventBus* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_bus;
	result = _tmp0_;
	return result;
}

static void
ft_event_producer_set_bus (FtEventProducer* self,
                           FtEventBus* value)
{
	FtEventBus* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = _g_object_ref0 (value);
	_g_object_unref0 (self->priv->_bus);
	self->priv->_bus = _tmp0_;
	g_object_notify_by_pspec ((GObject *) self, ft_event_producer_properties[FT_EVENT_PRODUCER_BUS_PROPERTY]);
}

static void
ft_event_producer_real_event (FtEventProducer* self,
                              FtEvent* event)
{
	FtEventBus* _tmp0_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (event != NULL);
	_tmp0_ = self->priv->_bus;
	ft_event_bus_push_event (_tmp0_, event);
}

static void
_g_free0_ (gpointer var)
{
	var = (g_free (var), NULL);
}

static GObject *
ft_event_producer_constructor (GType type,
                               guint n_construct_properties,
                               GObjectConstructParam * construct_properties)
{
	GObject * obj;
	GObjectClass * parent_class;
	static GWeakRef FtEventProducer_singleton__ref;
	static GMutex FtEventProducer_singleton__lock;
	FtEventProducer * self;
	FtEventSpec** _tmp0_;
	GHashFunc _tmp1_;
	GEqualFunc _tmp2_;
	GHashTable* _tmp3_;
	GQueue* _tmp4_;
	FtTrigger* _tmp5_;
	FtTrigger* _tmp6_;
	FtTrigger* _tmp7_;
	FtTrigger* _tmp8_;
	FtTrigger* _tmp9_;
	FtTrigger* _tmp10_;
	g_mutex_lock (&FtEventProducer_singleton__lock);
	obj = g_weak_ref_get (&FtEventProducer_singleton__ref);
	if (obj != NULL) {
		g_mutex_unlock (&FtEventProducer_singleton__lock);
		return obj;
	}
	parent_class = G_OBJECT_CLASS (ft_event_producer_parent_class);
	obj = parent_class->constructor (type, n_construct_properties, construct_properties);
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, FT_TYPE_EVENT_PRODUCER, FtEventProducer);
	_tmp0_ = g_new0 (FtEventSpec*, 0 + 1);
	self->priv->event_specs = (_vala_array_free (self->priv->event_specs, self->priv->event_specs_length1, (GDestroyNotify) ft_event_spec_unref), NULL);
	self->priv->event_specs = _tmp0_;
	self->priv->event_specs_length1 = 0;
	self->priv->_event_specs_size_ = self->priv->event_specs_length1;
	_tmp1_ = g_str_hash;
	_tmp2_ = g_str_equal;
	_tmp3_ = g_hash_table_new_full (_tmp1_, _tmp2_, _g_free0_, NULL);
	_g_hash_table_unref0 (self->priv->event_spec_by_name);
	self->priv->event_spec_by_name = _tmp3_;
	_tmp4_ = g_queue_new ();
	(self->priv->queue == NULL) ? NULL : (self->priv->queue = (g_queue_free (self->priv->queue), NULL));
	self->priv->queue = _tmp4_;
	_tmp5_ = g_new0 (FtTrigger, 0);
	self->priv->timer_state_change_triggers = (g_free (self->priv->timer_state_change_triggers), NULL);
	self->priv->timer_state_change_triggers = _tmp5_;
	self->priv->timer_state_change_triggers_length1 = 0;
	self->priv->_timer_state_change_triggers_size_ = self->priv->timer_state_change_triggers_length1;
	_tmp6_ = g_new0 (FtTrigger, 0);
	self->priv->session_manager_confirm_advancement_triggers = (g_free (self->priv->session_manager_confirm_advancement_triggers), NULL);
	self->priv->session_manager_confirm_advancement_triggers = _tmp6_;
	self->priv->session_manager_confirm_advancement_triggers_length1 = 0;
	self->priv->_session_manager_confirm_advancement_triggers_size_ = self->priv->session_manager_confirm_advancement_triggers_length1;
	_tmp7_ = g_new0 (FtTrigger, 0);
	self->priv->session_manager_advanced_triggers = (g_free (self->priv->session_manager_advanced_triggers), NULL);
	self->priv->session_manager_advanced_triggers = _tmp7_;
	self->priv->session_manager_advanced_triggers_length1 = 0;
	self->priv->_session_manager_advanced_triggers_size_ = self->priv->session_manager_advanced_triggers_length1;
	_tmp8_ = g_new0 (FtTrigger, 0);
	self->priv->session_manager_notify_current_state_triggers = (g_free (self->priv->session_manager_notify_current_state_triggers), NULL);
	self->priv->session_manager_notify_current_state_triggers = _tmp8_;
	self->priv->session_manager_notify_current_state_triggers_length1 = 0;
	self->priv->_session_manager_notify_current_state_triggers_size_ = self->priv->session_manager_notify_current_state_triggers_length1;
	_tmp9_ = g_new0 (FtTrigger, 0);
	self->priv->session_manager_session_rescheduled_triggers = (g_free (self->priv->session_manager_session_rescheduled_triggers), NULL);
	self->priv->session_manager_session_rescheduled_triggers = _tmp9_;
	self->priv->session_manager_session_rescheduled_triggers_length1 = 0;
	self->priv->_session_manager_session_rescheduled_triggers_size_ = self->priv->session_manager_session_rescheduled_triggers_length1;
	_tmp10_ = g_new0 (FtTrigger, 0);
	self->priv->session_manager_session_expired_triggers = (g_free (self->priv->session_manager_session_expired_triggers), NULL);
	self->priv->session_manager_session_expired_triggers = _tmp10_;
	self->priv->session_manager_session_expired_triggers_length1 = 0;
	self->priv->_session_manager_session_expired_triggers_size_ = self->priv->session_manager_session_expired_triggers_length1;
	ft_initialize_events (self);
	g_weak_ref_set (&FtEventProducer_singleton__ref, obj);
	g_mutex_unlock (&FtEventProducer_singleton__lock);
	return obj;
}

static void
ft_event_producer_class_init (FtEventProducerClass * klass,
                              gpointer klass_data)
{
	ft_event_producer_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &FtEventProducer_private_offset);
	((GObjectClass *) klass)->dispose = (void (*) (GObject*)) ft_event_producer_real_dispose;
	G_OBJECT_CLASS (klass)->get_property = _vala_ft_event_producer_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_ft_event_producer_set_property;
	G_OBJECT_CLASS (klass)->constructor = ft_event_producer_constructor;
	G_OBJECT_CLASS (klass)->finalize = ft_event_producer_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_EVENT_PRODUCER_SESSION_MANAGER_PROPERTY, ft_event_producer_properties[FT_EVENT_PRODUCER_SESSION_MANAGER_PROPERTY] = g_param_spec_object ("session-manager", "session-manager", "session-manager", FT_TYPE_SESSION_MANAGER, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_EVENT_PRODUCER_TIMER_PROPERTY, ft_event_producer_properties[FT_EVENT_PRODUCER_TIMER_PROPERTY] = g_param_spec_object ("timer", "timer", "timer", FT_TYPE_TIMER, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_EVENT_PRODUCER_BUS_PROPERTY, ft_event_producer_properties[FT_EVENT_PRODUCER_BUS_PROPERTY] = g_param_spec_object ("bus", "bus", "bus", FT_TYPE_EVENT_BUS, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
	ft_event_producer_signals[FT_EVENT_PRODUCER_EVENT_SIGNAL] = g_signal_new_class_handler ("event", FT_TYPE_EVENT_PRODUCER, G_SIGNAL_RUN_FIRST, (GCallback) ft_event_producer_real_event, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
}

static void
ft_event_producer_instance_init (FtEventProducer * self,
                                 gpointer klass)
{
	self->priv = ft_event_producer_get_instance_private (self);
	self->priv->_session_manager = NULL;
	self->priv->_timer = NULL;
	self->priv->_bus = NULL;
	self->priv->event_specs = NULL;
	self->priv->event_specs_length1 = 0;
	self->priv->_event_specs_size_ = self->priv->event_specs_length1;
	self->priv->event_spec_by_name = NULL;
	self->priv->queue = NULL;
	self->priv->idle_id = (guint) 0;
	self->priv->event_source_timestamp = FT_TIMESTAMP_UNDEFINED;
	self->priv->last_session_rescheduled_time = FT_TIMESTAMP_UNDEFINED;
	self->priv->destroying = FALSE;
}

static void
ft_event_producer_finalize (GObject * obj)
{
	FtEventProducer * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, FT_TYPE_EVENT_PRODUCER, FtEventProducer);
	_g_object_unref0 (self->priv->_session_manager);
	_g_object_unref0 (self->priv->_timer);
	_g_object_unref0 (self->priv->_bus);
	self->priv->event_specs = (_vala_array_free (self->priv->event_specs, self->priv->event_specs_length1, (GDestroyNotify) ft_event_spec_unref), NULL);
	_g_hash_table_unref0 (self->priv->event_spec_by_name);
	(self->priv->queue == NULL) ? NULL : (self->priv->queue = (g_queue_free (self->priv->queue), NULL));
	self->priv->timer_state_change_triggers = (g_free (self->priv->timer_state_change_triggers), NULL);
	self->priv->session_manager_confirm_advancement_triggers = (g_free (self->priv->session_manager_confirm_advancement_triggers), NULL);
	self->priv->session_manager_advanced_triggers = (g_free (self->priv->session_manager_advanced_triggers), NULL);
	self->priv->session_manager_notify_current_state_triggers = (g_free (self->priv->session_manager_notify_current_state_triggers), NULL);
	self->priv->session_manager_session_rescheduled_triggers = (g_free (self->priv->session_manager_session_rescheduled_triggers), NULL);
	self->priv->session_manager_session_expired_triggers = (g_free (self->priv->session_manager_session_expired_triggers), NULL);
	G_OBJECT_CLASS (ft_event_producer_parent_class)->finalize (obj);
}

/**
     * Gathers events from various sources and pushes them onto a bus. It's not 1:1 mapping; events are supposed to be
     * more intuitive for the user. Some events are filtered to not trigger them unnecessarily, and some are delayed
     * to collect fuller context.
     */
static GType
ft_event_producer_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (FtEventProducerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ft_event_producer_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (FtEventProducer), 0, (GInstanceInitFunc) ft_event_producer_instance_init, NULL };
	GType ft_event_producer_type_id;
	ft_event_producer_type_id = g_type_register_static (G_TYPE_OBJECT, "FtEventProducer", &g_define_type_info, 0);
	FtEventProducer_private_offset = g_type_add_instance_private (ft_event_producer_type_id, sizeof (FtEventProducerPrivate));
	return ft_event_producer_type_id;
}

GType
ft_event_producer_get_type (void)
{
	static volatile gsize ft_event_producer_type_id__once = 0;
	if (g_once_init_enter (&ft_event_producer_type_id__once)) {
		GType ft_event_producer_type_id;
		ft_event_producer_type_id = ft_event_producer_get_type_once ();
		g_once_init_leave (&ft_event_producer_type_id__once, ft_event_producer_type_id);
	}
	return ft_event_producer_type_id__once;
}

static void
_vala_ft_event_producer_get_property (GObject * object,
                                      guint property_id,
                                      GValue * value,
                                      GParamSpec * pspec)
{
	FtEventProducer * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, FT_TYPE_EVENT_PRODUCER, FtEventProducer);
	switch (property_id) {
		case FT_EVENT_PRODUCER_SESSION_MANAGER_PROPERTY:
		g_value_set_object (value, ft_event_producer_get_session_manager (self));
		break;
		case FT_EVENT_PRODUCER_TIMER_PROPERTY:
		g_value_set_object (value, ft_event_producer_get_timer (self));
		break;
		case FT_EVENT_PRODUCER_BUS_PROPERTY:
		g_value_set_object (value, ft_event_producer_get_bus (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_ft_event_producer_set_property (GObject * object,
                                      guint property_id,
                                      const GValue * value,
                                      GParamSpec * pspec)
{
	FtEventProducer * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, FT_TYPE_EVENT_PRODUCER, FtEventProducer);
	switch (property_id) {
		case FT_EVENT_PRODUCER_SESSION_MANAGER_PROPERTY:
		ft_event_producer_set_session_manager (self, g_value_get_object (value));
		break;
		case FT_EVENT_PRODUCER_TIMER_PROPERTY:
		ft_event_producer_set_timer (self, g_value_get_object (value));
		break;
		case FT_EVENT_PRODUCER_BUS_PROPERTY:
		ft_event_producer_set_bus (self, g_value_get_object (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_array_destroy (gpointer array,
                     gssize array_length,
                     GDestroyNotify destroy_func)
{
	if ((array != NULL) && (destroy_func != NULL)) {
		gssize i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}

static void
_vala_array_free (gpointer array,
                  gssize array_length,
                  GDestroyNotify destroy_func)
{
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

