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

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

#include "ft_core.h"
#include <string.h>
#include <glib.h>
#include <stdlib.h>
#include <glib-object.h>
#include <float.h>
#include <math.h>
#include <gio/gio.h>

#define FT_TIMER_TICKING_INTERVAL FT_INTERVAL_SECOND
#define FT_TIMER_TICKING_TOLERANCE (20 * FT_INTERVAL_MILLISECOND)
#define FT_TIMER_MIN_REMAINING_TIME_TO_SHORTEN (10 * FT_INTERVAL_SECOND)
#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

#define _g_variant_type_free0(var) ((var == NULL) ? NULL : (var = (g_variant_type_free (var), NULL)))
#define _g_variant_unref0(var) ((var == NULL) ? NULL : (var = (g_variant_unref (var), NULL)))
#define _g_variant_builder_unref0(var) ((var == NULL) ? NULL : (var = (g_variant_builder_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
#define _g_string_free0(var) ((var == NULL) ? NULL : (var = (g_string_free (var, TRUE), NULL)))
enum  {
	FT_TIMER_0_PROPERTY,
	FT_TIMER_STATE_PROPERTY,
	FT_TIMER_DURATION_PROPERTY,
	FT_TIMER_STARTED_TIME_PROPERTY,
	FT_TIMER_OFFSET_PROPERTY,
	FT_TIMER_USER_DATA_PROPERTY,
	FT_TIMER_NUM_PROPERTIES
};
static GParamSpec* ft_timer_properties[FT_TIMER_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _ft_timer_state_free0(var) ((var == NULL) ? NULL : (var = (ft_timer_state_free (var), NULL)))
#define _g_main_context_unref0(var) ((var == NULL) ? NULL : (var = (g_main_context_unref (var), NULL)))
enum  {
	FT_TIMER_RESOLVE_STATE_SIGNAL,
	FT_TIMER_STATE_CHANGED_SIGNAL,
	FT_TIMER_TICK_SIGNAL,
	FT_TIMER_FINISHED_SIGNAL,
	FT_TIMER_SYNCHRONIZED_SIGNAL,
	FT_TIMER_SUSPENDING_SIGNAL,
	FT_TIMER_SUSPENDED_SIGNAL,
	FT_TIMER_NUM_SIGNALS
};
static guint ft_timer_signals[FT_TIMER_NUM_SIGNALS] = {0};
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _FtTimerPrivate {
	FtTimerState _state;
	guint timeout_id;
	gint64 last_state_changed_time;
	gint64 last_tick_time;
	gint64 suspend_time;
	gboolean resolving_state;
	gint changing_state;
	FtTimerState* state_to_resolve;
	gint64 monotonic_time_offset;
	FtSleepMonitor* sleep_monitor;
	gulong prepare_for_sleep_id;
	gulong woke_up_id;
};

static gint FtTimer_private_offset;
static gpointer ft_timer_parent_class = NULL;
static FtTimer* ft_timer_instance;
static FtTimer* ft_timer_instance = NULL;

static void ft_timer_resolve_state (FtTimer* self,
                             FtTimerState* state,
                             gint64 timestamp);
static void ft_timer_state_changed (FtTimer* self,
                             const FtTimerState* current_state,
                             const FtTimerState* previous_state);
static void ft_timer_tick (FtTimer* self,
                    gint64 timestamp);
static void ft_timer_suspended (FtTimer* self,
                         gint64 start_time,
                         gint64 end_time);
static void ft_timer_start_timeout (FtTimer* self,
                             gint64 timestamp);
static inline void ft_timer_ensure_timestamp (FtTimer* self,
                                gint64* timestamp);
static void ft_timer_resolve_state_internal (FtTimer* self,
                                      FtTimerState* state,
                                      gint64 timestamp);
static void ft_timer_stop_timeout (FtTimer* self,
                            gint64 timestamp);
static gint64 ft_timer_round_seconds (FtTimer* self,
                               gint64 timestamp);
static gint64 ft_timer_calculate_tick_time (FtTimer* self,
                                     gint64 timestamp);
static gboolean ft_timer_on_timeout (FtTimer* self);
static gboolean ft_timer_on_timeout_once (FtTimer* self);
static gboolean _ft_timer_on_timeout_once_gsource_func (gpointer self);
static gboolean _ft_timer_on_timeout_gsource_func (gpointer self);
static void ft_timer_start_timeout_internal (FtTimer* self,
                                      gint64 timestamp);
static void ft_timer_real_dispose (GObject* base);
static void g_cclosure_user_marshal_VOID__POINTER_INT64 (GClosure * closure,
                                                  GValue * return_value,
                                                  guint n_param_values,
                                                  const GValue * param_values,
                                                  gpointer invocation_hint,
                                                  gpointer marshal_data);
static void g_cclosure_user_marshal_VOID__BOXED_BOXED (GClosure * closure,
                                                GValue * return_value,
                                                guint n_param_values,
                                                const GValue * param_values,
                                                gpointer invocation_hint,
                                                gpointer marshal_data);
static void g_cclosure_user_marshal_VOID__INT64 (GClosure * closure,
                                          GValue * return_value,
                                          guint n_param_values,
                                          const GValue * param_values,
                                          gpointer invocation_hint,
                                          gpointer marshal_data);
static void g_cclosure_user_marshal_VOID__INT64_INT64 (GClosure * closure,
                                                GValue * return_value,
                                                guint n_param_values,
                                                const GValue * param_values,
                                                gpointer invocation_hint,
                                                gpointer marshal_data);
static GObject * ft_timer_constructor (GType type,
                                guint n_construct_properties,
                                GObjectConstructParam * construct_properties);
static void _ft_timer___lambda29_ (FtTimer* self);
static void __ft_timer___lambda29__ft_sleep_monitor_prepare_for_sleep (FtSleepMonitor* _sender,
                                                                gpointer self);
static void _ft_timer___lambda30_ (FtTimer* self);
static void __ft_timer___lambda30__ft_sleep_monitor_woke_up (FtSleepMonitor* _sender,
                                                      gpointer self);
static void ft_timer_finalize (GObject * obj);
static GType ft_timer_get_type_once (void);
static void _vala_ft_timer_get_property (GObject * object,
                                  guint property_id,
                                  GValue * value,
                                  GParamSpec * pspec);
static void _vala_ft_timer_set_property (GObject * object,
                                  guint property_id,
                                  const GValue * value,
                                  GParamSpec * pspec);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

void
ft_timer_state_init (FtTimerState *self)
{
	memset (self, 0, sizeof (FtTimerState));
	(*self).duration = (gint64) 0;
	(*self).offset = (gint64) 0;
	(*self).started_time = FT_TIMESTAMP_UNDEFINED;
	(*self).paused_time = FT_TIMESTAMP_UNDEFINED;
	(*self).finished_time = FT_TIMESTAMP_UNDEFINED;
	(*self).user_data = NULL;
}

/**
         * Make state copy
         *
         * This function is unnecessary. Structs in vala are copied by default. It's kept
         * to bring more clarity to our code.
         */
void
ft_timer_state_copy (FtTimerState *self,
                     FtTimerState* result)
{
	*result = (*self);
	return;
}

gboolean
ft_timer_state_equals (FtTimerState *self,
                       const FtTimerState* other)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_ = FALSE;
	gboolean _tmp4_ = FALSE;
	FtTimerState _tmp5_;
	gboolean result;
	g_return_val_if_fail (other != NULL, FALSE);
	_tmp5_ = *other;
	if ((*self).duration == _tmp5_.duration) {
		FtTimerState _tmp6_;
		_tmp6_ = *other;
		_tmp4_ = (*self).offset == _tmp6_.offset;
	} else {
		_tmp4_ = FALSE;
	}
	if (_tmp4_) {
		FtTimerState _tmp7_;
		_tmp7_ = *other;
		_tmp3_ = (*self).started_time == _tmp7_.started_time;
	} else {
		_tmp3_ = FALSE;
	}
	if (_tmp3_) {
		FtTimerState _tmp8_;
		_tmp8_ = *other;
		_tmp2_ = (*self).paused_time == _tmp8_.paused_time;
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		FtTimerState _tmp9_;
		_tmp9_ = *other;
		_tmp1_ = (*self).finished_time == _tmp9_.finished_time;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		void* _tmp10_;
		FtTimerState _tmp11_;
		void* _tmp12_;
		_tmp10_ = (*self).user_data;
		_tmp11_ = *other;
		_tmp12_ = _tmp11_.user_data;
		_tmp0_ = _tmp10_ == _tmp12_;
	} else {
		_tmp0_ = FALSE;
	}
	result = _tmp0_;
	return result;
}

gboolean
ft_timer_state_is_valid (FtTimerState *self)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_ = FALSE;
	gboolean result;
	if ((*self).duration < ((gint64) 0)) {
		result = FALSE;
		return result;
	}
	if (ft_timestamp_is_defined ((*self).finished_time)) {
		_tmp0_ = ft_timestamp_is_undefined ((*self).started_time);
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		result = FALSE;
		return result;
	}
	if (ft_timestamp_is_defined ((*self).finished_time)) {
		_tmp1_ = ft_timestamp_is_defined ((*self).paused_time);
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		result = FALSE;
		return result;
	}
	if (ft_timestamp_is_defined ((*self).paused_time)) {
		_tmp2_ = (*self).paused_time < (*self).started_time;
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		result = FALSE;
		return result;
	}
	if (ft_timestamp_is_defined ((*self).finished_time)) {
		_tmp3_ = (*self).finished_time < (*self).started_time;
	} else {
		_tmp3_ = FALSE;
	}
	if (_tmp3_) {
		result = FALSE;
		return result;
	}
	result = TRUE;
	return result;
}

inline gboolean
ft_timer_state_is_started (FtTimerState *self)
{
	gboolean result;
	result = ft_timestamp_is_defined ((*self).started_time);
	return result;
}

inline gboolean
ft_timer_state_is_running (FtTimerState *self)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean result;
	if (ft_timestamp_is_defined ((*self).started_time)) {
		_tmp1_ = ft_timestamp_is_undefined ((*self).paused_time);
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		_tmp0_ = ft_timestamp_is_undefined ((*self).finished_time);
	} else {
		_tmp0_ = FALSE;
	}
	result = _tmp0_;
	return result;
}

inline gboolean
ft_timer_state_is_paused (FtTimerState *self)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean result;
	if (ft_timestamp_is_defined ((*self).paused_time)) {
		_tmp1_ = ft_timestamp_is_defined ((*self).started_time);
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		_tmp0_ = ft_timestamp_is_undefined ((*self).finished_time);
	} else {
		_tmp0_ = FALSE;
	}
	result = _tmp0_;
	return result;
}

inline gboolean
ft_timer_state_is_finished (FtTimerState *self)
{
	gboolean result;
	result = ft_timestamp_is_defined ((*self).finished_time);
	return result;
}

/**
         * Calculate elapsed time.
         *
         * It's only accurate when passing a current time. If you pass a historic time
         * the result will be just an estimate.
         */
gint64
ft_timer_state_calculate_elapsed (FtTimerState *self,
                                  gint64 timestamp)
{
	gint64 result;
	if (ft_timestamp_is_undefined ((*self).started_time)) {
		result = (gint64) 0;
		return result;
	}
	if (ft_timestamp_is_defined ((*self).paused_time)) {
		timestamp = MIN ((*self).paused_time, timestamp);
	}
	if (ft_timestamp_is_defined ((*self).finished_time)) {
		timestamp = MIN ((*self).finished_time, timestamp);
	}
	result = CLAMP ((timestamp - (*self).started_time) - (*self).offset, (gint64) 0, (*self).duration);
	return result;
}

/**
         * Calculate remaining time.
         *
         * It's only accurate when passing a current time. If you pass a historic time
         * the result will be just an estimate.
         */
gint64
ft_timer_state_calculate_remaining (FtTimerState *self,
                                    gint64 timestamp)
{
	gint64 result;
	result = (*self).duration - ft_timer_state_calculate_elapsed (&(*self), timestamp);
	return result;
}

/**
         * Convert structure to Variant.
         *
         * Used in tests.
         */
GVariant*
ft_timer_state_to_variant (FtTimerState *self)
{
	GVariantBuilder* builder = NULL;
	GVariantType* _tmp0_;
	GVariantType* _tmp1_;
	GVariantBuilder* _tmp2_;
	GVariantBuilder* _tmp3_;
	GVariant* _tmp4_;
	GVariant* _tmp5_;
	GVariant* _tmp6_;
	GVariant* _tmp7_;
	GVariant* _tmp8_;
	GVariant* _tmp9_;
	GVariant* _tmp10_;
	GVariant* _tmp11_;
	GVariant* _tmp12_;
	GVariant* _tmp13_;
	GVariant* _tmp14_;
	GVariant* result;
	_tmp0_ = g_variant_type_new ("a{s*}");
	_tmp1_ = _tmp0_;
	_tmp2_ = g_variant_builder_new (_tmp1_);
	_tmp3_ = _tmp2_;
	_g_variant_type_free0 (_tmp1_);
	builder = _tmp3_;
	_tmp4_ = g_variant_new_int64 ((*self).duration);
	g_variant_ref_sink (_tmp4_);
	_tmp5_ = _tmp4_;
	g_variant_builder_add (builder, "{sv}", "duration", _tmp5_, NULL);
	_g_variant_unref0 (_tmp5_);
	_tmp6_ = g_variant_new_int64 ((*self).offset);
	g_variant_ref_sink (_tmp6_);
	_tmp7_ = _tmp6_;
	g_variant_builder_add (builder, "{sv}", "offset", _tmp7_, NULL);
	_g_variant_unref0 (_tmp7_);
	_tmp8_ = g_variant_new_int64 ((*self).started_time);
	g_variant_ref_sink (_tmp8_);
	_tmp9_ = _tmp8_;
	g_variant_builder_add (builder, "{sv}", "started_time", _tmp9_, NULL);
	_g_variant_unref0 (_tmp9_);
	_tmp10_ = g_variant_new_int64 ((*self).paused_time);
	g_variant_ref_sink (_tmp10_);
	_tmp11_ = _tmp10_;
	g_variant_builder_add (builder, "{sv}", "paused_time", _tmp11_, NULL);
	_g_variant_unref0 (_tmp11_);
	_tmp12_ = g_variant_new_int64 ((*self).finished_time);
	g_variant_ref_sink (_tmp12_);
	_tmp13_ = _tmp12_;
	g_variant_builder_add (builder, "{sv}", "finished_time", _tmp13_, NULL);
	_g_variant_unref0 (_tmp13_);
	_tmp14_ = g_variant_builder_end (builder);
	g_variant_ref_sink (_tmp14_);
	result = _tmp14_;
	_g_variant_builder_unref0 (builder);
	return result;
}

/**
         * Represent state as string.
         *
         * Used in tests.
         */
gchar*
ft_timer_state_to_representation (FtTimerState *self)
{
	GString* representation = NULL;
	GString* _tmp0_;
	GString* _tmp1_;
	gchar* _tmp2_;
	gchar* _tmp3_;
	gchar* _tmp4_;
	gchar* _tmp5_;
	GString* _tmp6_;
	gchar* _tmp7_;
	gchar* _tmp8_;
	gchar* _tmp9_;
	gchar* _tmp10_;
	GString* _tmp11_;
	gchar* _tmp12_;
	gchar* _tmp13_;
	gchar* _tmp14_;
	gchar* _tmp15_;
	GString* _tmp16_;
	gchar* _tmp17_;
	gchar* _tmp18_;
	gchar* _tmp19_;
	gchar* _tmp20_;
	GString* _tmp21_;
	gchar* _tmp22_;
	gchar* _tmp23_;
	gchar* _tmp24_;
	gchar* _tmp25_;
	const gchar* _tmp26_ = NULL;
	void* _tmp27_;
	GString* _tmp28_;
	GString* _tmp29_;
	GString* _tmp30_;
	const gchar* _tmp31_;
	gchar* _tmp32_;
	gchar* result;
	_tmp0_ = g_string_new ("TimerState (\n");
	representation = _tmp0_;
	_tmp1_ = representation;
	_tmp2_ = g_strdup_printf ("%" G_GINT64_FORMAT, (*self).duration);
	_tmp3_ = _tmp2_;
	_tmp4_ = g_strconcat ("    duration = ", _tmp3_, ",\n", NULL);
	_tmp5_ = _tmp4_;
	g_string_append (_tmp1_, _tmp5_);
	_g_free0 (_tmp5_);
	_g_free0 (_tmp3_);
	_tmp6_ = representation;
	_tmp7_ = g_strdup_printf ("%" G_GINT64_FORMAT, (*self).offset);
	_tmp8_ = _tmp7_;
	_tmp9_ = g_strconcat ("    offset = ", _tmp8_, ",\n", NULL);
	_tmp10_ = _tmp9_;
	g_string_append (_tmp6_, _tmp10_);
	_g_free0 (_tmp10_);
	_g_free0 (_tmp8_);
	_tmp11_ = representation;
	_tmp12_ = g_strdup_printf ("%" G_GINT64_FORMAT, (*self).started_time);
	_tmp13_ = _tmp12_;
	_tmp14_ = g_strconcat ("    started_time = ", _tmp13_, ",\n", NULL);
	_tmp15_ = _tmp14_;
	g_string_append (_tmp11_, _tmp15_);
	_g_free0 (_tmp15_);
	_g_free0 (_tmp13_);
	_tmp16_ = representation;
	_tmp17_ = g_strdup_printf ("%" G_GINT64_FORMAT, (*self).paused_time);
	_tmp18_ = _tmp17_;
	_tmp19_ = g_strconcat ("    paused_time = ", _tmp18_, ",\n", NULL);
	_tmp20_ = _tmp19_;
	g_string_append (_tmp16_, _tmp20_);
	_g_free0 (_tmp20_);
	_g_free0 (_tmp18_);
	_tmp21_ = representation;
	_tmp22_ = g_strdup_printf ("%" G_GINT64_FORMAT, (*self).finished_time);
	_tmp23_ = _tmp22_;
	_tmp24_ = g_strconcat ("    finished_time = ", _tmp23_, ",\n", NULL);
	_tmp25_ = _tmp24_;
	g_string_append (_tmp21_, _tmp25_);
	_g_free0 (_tmp25_);
	_g_free0 (_tmp23_);
	_tmp27_ = (*self).user_data;
	if (_tmp27_ == NULL) {
		_tmp26_ = "    user_data = null\n";
	} else {
		_tmp26_ = "    user_data = not null\n";
	}
	_tmp28_ = representation;
	g_string_append (_tmp28_, _tmp26_);
	_tmp29_ = representation;
	g_string_append (_tmp29_, ")");
	_tmp30_ = representation;
	_tmp31_ = _tmp30_->str;
	_tmp32_ = g_strdup (_tmp31_);
	result = _tmp32_;
	_g_string_free0 (representation);
	return result;
}

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

void
ft_timer_state_free (FtTimerState* self)
{
	g_free (self);
}

static GType
ft_timer_state_get_type_once (void)
{
	GType ft_timer_state_type_id;
	ft_timer_state_type_id = g_boxed_type_register_static ("FtTimerState", (GBoxedCopyFunc) ft_timer_state_dup, (GBoxedFreeFunc) ft_timer_state_free);
	return ft_timer_state_type_id;
}

GType
ft_timer_state_get_type (void)
{
	static volatile gsize ft_timer_state_type_id__once = 0;
	if (g_once_init_enter (&ft_timer_state_type_id__once)) {
		GType ft_timer_state_type_id;
		ft_timer_state_type_id = ft_timer_state_get_type_once ();
		g_once_init_leave (&ft_timer_state_type_id__once, ft_timer_state_type_id);
	}
	return ft_timer_state_type_id__once;
}

static inline gpointer
ft_timer_get_instance_private (FtTimer* self)
{
	return G_STRUCT_MEMBER_P (self, FtTimer_private_offset);
}

FtTimer*
ft_timer_construct (GType object_type,
                    gint64 duration,
                    void* user_data)
{
	FtTimer * self = NULL;
	FtTimerState _tmp0_ = {0};
	_vala_return_val_if_fail (duration >= ((gint64) 0), "duration >= 0", NULL);
	self = (FtTimer*) g_object_new (object_type, NULL);
	ft_timer_state_init (&_tmp0_);
	_tmp0_.duration = duration;
	_tmp0_.offset = (gint64) 0;
	_tmp0_.started_time = FT_TIMESTAMP_UNDEFINED;
	_tmp0_.paused_time = FT_TIMESTAMP_UNDEFINED;
	_tmp0_.finished_time = FT_TIMESTAMP_UNDEFINED;
	_tmp0_.user_data = user_data;
	self->priv->_state = _tmp0_;
	return self;
}

FtTimer*
ft_timer_new (gint64 duration,
              void* user_data)
{
	return ft_timer_construct (FT_TYPE_TIMER, duration, user_data);
}

FtTimer*
ft_timer_construct_with_state (GType object_type,
                               const FtTimerState* state)
{
	FtTimer * self = NULL;
	FtTimerState _tmp0_;
	FtTimerState _tmp1_;
	g_return_val_if_fail (state != NULL, NULL);
	self = (FtTimer*) g_object_new (object_type, NULL);
	_tmp0_ = *state;
	self->priv->_state = _tmp0_;
	_tmp1_ = self->priv->_state;
	if (ft_timestamp_is_defined (_tmp1_.started_time)) {
		self->priv->last_state_changed_time = ft_timestamp_from_now ();
		ft_timer_start_timeout (self, self->priv->last_state_changed_time);
	}
	return self;
}

FtTimer*
ft_timer_new_with_state (const FtTimerState* state)
{
	return ft_timer_construct_with_state (FT_TYPE_TIMER, state);
}

/**
         * Try to change state and update fields related to state change
         */
void
ft_timer_set_state_full (FtTimer* self,
                         const FtTimerState* state,
                         gint64 timestamp)
{
	FtTimerState previous_state = {0};
	FtTimerState _tmp0_;
	FtTimerState _tmp3_;
	FtTimerState _tmp4_;
	gint _tmp5_;
	gboolean _tmp6_ = FALSE;
	FtTimerState _tmp7_;
	FtTimerState _tmp8_;
	FtTimerState _tmp11_;
	FtTimerState _tmp12_;
	FtTimerState _tmp13_;
	FtTimerState _tmp14_;
	FtTimerState _tmp15_;
	FtTimerState _tmp16_;
	FtTimerState _tmp17_;
	void* _tmp18_;
	FtTimerState _tmp19_;
	void* _tmp20_;
	FtTimerState _tmp21_;
	FtTimerState _tmp22_;
	gint _tmp23_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (state != NULL);
	ft_timer_ensure_timestamp (self, &timestamp);
	_tmp0_ = self->priv->_state;
	previous_state = _tmp0_;
	ft_timer_resolve_state_internal (self, state, timestamp);
	if (!ft_timer_state_is_valid (state)) {
		gchar* _tmp1_;
		gchar* _tmp2_;
		_tmp1_ = ft_timer_state_to_representation (state);
		_tmp2_ = _tmp1_;
		g_error ("timer.vala:374: Trying to set timer an invalid state: %s", _tmp2_);
		_g_free0 (_tmp2_);
	}
	_tmp3_ = *state;
	if (ft_timer_state_equals (&self->priv->_state, &_tmp3_)) {
		return;
	}
	self->priv->last_state_changed_time = timestamp;
	_tmp4_ = *state;
	self->priv->_state = _tmp4_;
	_tmp5_ = self->priv->changing_state;
	self->priv->changing_state = _tmp5_ + 1;
	_tmp7_ = *state;
	_tmp8_ = previous_state;
	if (_tmp7_.started_time != _tmp8_.started_time) {
		_tmp6_ = TRUE;
	} else {
		FtTimerState _tmp9_;
		FtTimerState _tmp10_;
		_tmp9_ = *state;
		_tmp10_ = previous_state;
		_tmp6_ = _tmp9_.offset != _tmp10_.offset;
	}
	if (_tmp6_) {
		ft_timer_stop_timeout (self, timestamp);
	}
	g_object_notify ((GObject*) self, "state");
	_tmp11_ = *state;
	_tmp12_ = previous_state;
	if (_tmp11_.duration != _tmp12_.duration) {
		g_object_notify ((GObject*) self, "duration");
	}
	_tmp13_ = *state;
	_tmp14_ = previous_state;
	if (_tmp13_.started_time != _tmp14_.started_time) {
		g_object_notify ((GObject*) self, "started-time");
	}
	_tmp15_ = *state;
	_tmp16_ = previous_state;
	if (_tmp15_.offset != _tmp16_.offset) {
		g_object_notify ((GObject*) self, "offset");
	}
	_tmp17_ = *state;
	_tmp18_ = _tmp17_.user_data;
	_tmp19_ = previous_state;
	_tmp20_ = _tmp19_.user_data;
	if (_tmp18_ != _tmp20_) {
		g_object_notify ((GObject*) self, "user-data");
	}
	_tmp21_ = self->priv->_state;
	_tmp22_ = previous_state;
	g_signal_emit (self, ft_timer_signals[FT_TIMER_STATE_CHANGED_SIGNAL], 0, &_tmp21_, &_tmp22_);
	_tmp23_ = self->priv->changing_state;
	self->priv->changing_state = _tmp23_ - 1;
}

void
ft_timer_set_duration_full (FtTimer* self,
                            gint64 duration,
                            gint64 timestamp)
{
	FtTimerState _tmp0_;
	FtTimerState new_state = {0};
	FtTimerState _tmp1_ = {0};
	FtTimerState _tmp2_;
	FtTimerState _tmp3_;
	FtTimerState _tmp4_;
	g_return_if_fail (self != NULL);
	if (duration < ((gint64) 0)) {
		g_debug ("timer.vala:419: Trying to set a negative timer duration (%.1fs).", ft_timestamp_to_seconds (duration));
		duration = (gint64) 0;
	}
	_tmp0_ = self->priv->_state;
	if (duration == _tmp0_.duration) {
		return;
	}
	ft_timer_state_copy (&self->priv->_state, &_tmp1_);
	new_state = _tmp1_;
	new_state.duration = duration;
	_tmp2_ = new_state;
	_tmp3_ = self->priv->_state;
	if (_tmp2_.duration > _tmp3_.duration) {
		new_state.finished_time = FT_TIMESTAMP_UNDEFINED;
	}
	_tmp4_ = new_state;
	ft_timer_set_state_full (self, &_tmp4_, timestamp);
}

/**
         * Resolve timer state.
         *
         * It's a wrapper for `this.resolve_state`, handling a possible recursion.
         */
static gpointer
_ft_timer_state_dup0 (gpointer self)
{
	return self ? ft_timer_state_dup (self) : NULL;
}

static void
ft_timer_resolve_state_internal (FtTimer* self,
                                 FtTimerState* state,
                                 gint64 timestamp)
{
	gint recursion_count = 0;
	FtTimerState _tmp2_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (state != NULL);
	recursion_count = 0;
	if (self->priv->resolving_state) {
		FtTimerState _tmp0_;
		FtTimerState* _tmp1_;
		_tmp0_ = *state;
		_tmp1_ = _ft_timer_state_dup0 (&_tmp0_);
		_ft_timer_state_free0 (self->priv->state_to_resolve);
		self->priv->state_to_resolve = _tmp1_;
		return;
	}
	_tmp2_ = *state;
	if (ft_timer_state_equals (&self->priv->_state, &_tmp2_)) {
		return;
	}
	self->priv->resolving_state = TRUE;
	while (TRUE) {
		FtTimerState* _tmp3_;
		FtTimerState* _tmp4_;
		gint _tmp5_;
		g_signal_emit (self, ft_timer_signals[FT_TIMER_RESOLVE_STATE_SIGNAL], 0, state, timestamp);
		_tmp3_ = self->priv->state_to_resolve;
		if (_tmp3_ == NULL) {
			break;
		}
		if (recursion_count > 1) {
			g_error ("timer.vala:468: Reached recursion limit while resolving timer state");
		}
		_tmp4_ = self->priv->state_to_resolve;
		*state = *_tmp4_;
		_ft_timer_state_free0 (self->priv->state_to_resolve);
		self->priv->state_to_resolve = NULL;
		_tmp5_ = recursion_count;
		recursion_count = _tmp5_ + 1;
	}
	self->priv->resolving_state = FALSE;
}

/**
         * Sets a default `Timer`.
         *
         * The old default timer is unreffed and the new timer referenced.
         *
         * A value of null for this will cause the current default timer to be released and a new default timer
         * to be created on demand.
         */
static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

void
ft_timer_set_default (FtTimer* timer)
{
	FtTimer* _tmp0_;
	_tmp0_ = _g_object_ref0 (timer);
	_g_object_unref0 (ft_timer_instance);
	ft_timer_instance = _tmp0_;
}

/**
         * Return a default timer.
         *
         * A new default timer will be created on demand.
         */
FtTimer*
ft_timer_get_default (void)
{
	FtTimer* _tmp0_;
	FtTimer* _tmp3_;
	FtTimer* result;
	_tmp0_ = ft_timer_instance;
	if (_tmp0_ == NULL) {
		FtTimer* _tmp1_;
		FtTimer* _tmp2_;
		_tmp1_ = ft_timer_new ((gint64) 0, NULL);
		_tmp2_ = _tmp1_;
		ft_timer_set_default (_tmp2_);
		_g_object_unref0 (_tmp2_);
	}
	_tmp3_ = ft_timer_instance;
	result = _tmp3_;
	return result;
}

gboolean
ft_timer_is_default (FtTimer* self)
{
	FtTimer* _tmp0_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = ft_timer_instance;
	result = _tmp0_ == self;
	return result;
}

/**
         * Return whether timer is ticking -- whether timer has started, is not paused and hasn't finished.
         */
gboolean
ft_timer_is_running (FtTimer* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = ft_timer_state_is_running (&self->priv->_state);
	return result;
}

/**
         * Return whether timer has been started.
         */
gboolean
ft_timer_is_started (FtTimer* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = ft_timer_state_is_started (&self->priv->_state);
	return result;
}

/**
         * Return whether timer is paused.
         */
gboolean
ft_timer_is_paused (FtTimer* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = ft_timer_state_is_paused (&self->priv->_state);
	return result;
}

/**
         * Return whether timer has finished.
         *
         * It does not need to reach full time for timer to be marked as finished.
         */
gboolean
ft_timer_is_finished (FtTimer* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = ft_timer_state_is_finished (&self->priv->_state);
	return result;
}

/**
         * Reset timer to initial state.
         */
void
ft_timer_reset (FtTimer* self,
                gint64 duration,
                void* user_data,
                gint64 timestamp)
{
	FtTimerState _tmp0_ = {0};
	g_return_if_fail (self != NULL);
	_vala_return_if_fail (duration >= ((gint64) 0), "duration >= 0");
	ft_timer_state_init (&_tmp0_);
	_tmp0_.duration = duration;
	_tmp0_.offset = (gint64) 0;
	_tmp0_.started_time = FT_TIMESTAMP_UNDEFINED;
	_tmp0_.paused_time = FT_TIMESTAMP_UNDEFINED;
	_tmp0_.finished_time = FT_TIMESTAMP_UNDEFINED;
	_tmp0_.user_data = user_data;
	ft_timer_set_state_full (self, &_tmp0_, timestamp);
}

/**
         * Start the timer or continue where it left off.
         */
void
ft_timer_start (FtTimer* self,
                gint64 timestamp)
{
	gboolean _tmp0_ = FALSE;
	FtTimerState new_state = {0};
	FtTimerState _tmp1_ = {0};
	FtTimerState _tmp2_;
	g_return_if_fail (self != NULL);
	if (ft_timer_is_started (self)) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = ft_timer_is_finished (self);
	}
	if (_tmp0_) {
		return;
	}
	ft_timer_ensure_timestamp (self, &timestamp);
	ft_timer_state_copy (&self->priv->_state, &_tmp1_);
	new_state = _tmp1_;
	new_state.started_time = timestamp;
	new_state.paused_time = FT_TIMESTAMP_UNDEFINED;
	_tmp2_ = new_state;
	ft_timer_set_state_full (self, &_tmp2_, timestamp);
}

/**
         * Stop the timer if it's running.
         */
void
ft_timer_pause (FtTimer* self,
                gint64 timestamp)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	FtTimerState new_state = {0};
	FtTimerState _tmp2_ = {0};
	FtTimerState _tmp3_;
	g_return_if_fail (self != NULL);
	if (ft_timer_is_paused (self)) {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = !ft_timer_is_started (self);
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = ft_timer_is_finished (self);
	}
	if (_tmp0_) {
		return;
	}
	ft_timer_ensure_timestamp (self, &timestamp);
	ft_timer_state_copy (&self->priv->_state, &_tmp2_);
	new_state = _tmp2_;
	new_state.paused_time = ft_timer_round_seconds (self, timestamp);
	_tmp3_ = new_state;
	ft_timer_set_state_full (self, &_tmp3_, timestamp);
}

/**
         * Resume timer if paused.
         */
void
ft_timer_resume (FtTimer* self,
                 gint64 timestamp)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	FtTimerState new_state = {0};
	FtTimerState _tmp2_ = {0};
	FtTimerState _tmp3_;
	FtTimerState _tmp4_;
	g_return_if_fail (self != NULL);
	if (!ft_timer_is_started (self)) {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = ft_timer_is_finished (self);
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = !ft_timer_is_paused (self);
	}
	if (_tmp0_) {
		return;
	}
	ft_timer_ensure_timestamp (self, &timestamp);
	ft_timer_state_copy (&self->priv->_state, &_tmp2_);
	new_state = _tmp2_;
	_tmp3_ = new_state;
	new_state.offset = new_state.offset + (timestamp - _tmp3_.paused_time);
	new_state.paused_time = FT_TIMESTAMP_UNDEFINED;
	_tmp4_ = new_state;
	ft_timer_set_state_full (self, &_tmp4_, timestamp);
}

/**
         * Rewind
         */
void
ft_timer_rewind (FtTimer* self,
                 gint64 interval,
                 gint64 timestamp)
{
	gint64 elapsed = 0LL;
	gint64 new_elapsed = 0LL;
	FtTimerState new_state = {0};
	FtTimerState _tmp0_ = {0};
	FtTimerState _tmp1_;
	FtTimerState _tmp5_;
	g_return_if_fail (self != NULL);
	if (!ft_timer_is_started (self)) {
		return;
	}
	if (interval == ((gint64) 0)) {
		return;
	}
	if (interval < ((gint64) 0)) {
		g_debug ("timer.vala:637: Rewinding timer with negative value (%.1fs).", ft_timestamp_to_seconds (interval));
	}
	ft_timer_ensure_timestamp (self, &timestamp);
	elapsed = ft_timer_calculate_elapsed (self, timestamp);
	new_elapsed = ft_timestamp_round (MAX (elapsed - interval, (gint64) 0), FT_TIMER_TICKING_INTERVAL);
	ft_timer_state_copy (&self->priv->_state, &_tmp0_);
	new_state = _tmp0_;
	new_state.finished_time = FT_TIMESTAMP_UNDEFINED;
	_tmp1_ = new_state;
	if (ft_timestamp_is_defined (_tmp1_.paused_time)) {
		FtTimerState _tmp2_;
		FtTimerState _tmp3_;
		_tmp2_ = new_state;
		_tmp3_ = new_state;
		new_state.offset = (_tmp2_.paused_time - _tmp3_.started_time) - new_elapsed;
	} else {
		FtTimerState _tmp4_;
		_tmp4_ = new_state;
		new_state.offset = (timestamp - _tmp4_.started_time) - new_elapsed;
	}
	_tmp5_ = new_state;
	ft_timer_set_state_full (self, &_tmp5_, timestamp);
}

/**
         * Extend
         */
void
ft_timer_extend (FtTimer* self,
                 gint64 interval,
                 gint64 timestamp)
{
	gint64 _tmp0_;
	gint64 _tmp1_;
	gint64 elapsed = 0LL;
	gint64 remaining = 0LL;
	FtTimerState _tmp2_;
	gint64 _tmp3_ = 0LL;
	g_return_if_fail (self != NULL);
	_tmp0_ = ft_timer_get_duration (self);
	_tmp1_ = _tmp0_;
	if (_tmp1_ <= ((gint64) 0)) {
		return;
	}
	if (interval == ((gint64) 0)) {
		return;
	}
	ft_timer_ensure_timestamp (self, &timestamp);
	elapsed = ft_timer_calculate_elapsed (self, timestamp);
	_tmp2_ = self->priv->_state;
	remaining = _tmp2_.duration - elapsed;
	if ((remaining + interval) >= FT_TIMER_MIN_REMAINING_TIME_TO_SHORTEN) {
		_tmp3_ = remaining + interval;
	} else {
		_tmp3_ = FT_TIMER_MIN_REMAINING_TIME_TO_SHORTEN;
	}
	remaining = _tmp3_;
	ft_timer_set_duration_full (self, elapsed + remaining, timestamp);
}

/**
         * Mark state as "finished".
         *
         * Do not use it. It's public only for unit-tests.
         */
void
ft_timer_finish (FtTimer* self,
                 gint64 timestamp)
{
	FtTimerState new_state = {0};
	FtTimerState _tmp0_ = {0};
	FtTimerState _tmp1_;
	FtTimerState _tmp3_;
	g_return_if_fail (self != NULL);
	if (ft_timer_is_finished (self)) {
		return;
	}
	ft_timer_ensure_timestamp (self, &timestamp);
	ft_timer_stop_timeout (self, timestamp);
	ft_timer_state_copy (&self->priv->_state, &_tmp0_);
	new_state = _tmp0_;
	new_state.finished_time = timestamp;
	_tmp1_ = new_state;
	if (ft_timestamp_is_defined (_tmp1_.paused_time)) {
		FtTimerState _tmp2_;
		_tmp2_ = new_state;
		new_state.offset = new_state.offset + (timestamp - _tmp2_.paused_time);
		new_state.paused_time = FT_TIMESTAMP_UNDEFINED;
	}
	_tmp3_ = new_state;
	ft_timer_set_state_full (self, &_tmp3_, timestamp);
}

void
ft_timer_synchronize (FtTimer* self,
                      gint64 monotonic_time,
                      gint64 real_time)
{
	g_return_if_fail (self != NULL);
	if (ft_timestamp_is_undefined (real_time)) {
		real_time = ft_timestamp_from_now ();
	}
	if (ft_timestamp_is_undefined (monotonic_time)) {
		monotonic_time = g_get_monotonic_time ();
	}
	self->priv->monotonic_time_offset = real_time - monotonic_time;
	g_signal_emit (self, ft_timer_signals[FT_TIMER_SYNCHRONIZED_SIGNAL], 0);
}

/**
         * Return approximate real time.
         */
gint64
ft_timer_get_current_time (FtTimer* self,
                           gint64 monotonic_time)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gint64 result;
	g_return_val_if_fail (self != NULL, -1LL);
	if (self->priv->changing_state > 0) {
		_tmp0_ = ft_timestamp_is_undefined (monotonic_time);
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		result = self->priv->last_state_changed_time;
		return result;
	}
	if (self->priv->monotonic_time_offset == ((gint64) 0)) {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = ft_timestamp_is_frozen ();
	}
	if (_tmp1_) {
		result = ft_timestamp_from_now ();
		return result;
	}
	if (ft_timestamp_is_undefined (monotonic_time)) {
		monotonic_time = g_get_monotonic_time ();
	}
	result = monotonic_time + self->priv->monotonic_time_offset;
	return result;
}

static gint64
ft_timer_round_seconds (FtTimer* self,
                        gint64 timestamp)
{
	gboolean _tmp0_ = FALSE;
	FtTimerState _tmp1_;
	gint64 result;
	g_return_val_if_fail (self != NULL, -1LL);
	if (self->priv->last_tick_time > ((gint64) 0)) {
		_tmp0_ = llabs (timestamp - self->priv->last_tick_time) < (2 * FT_TIMER_TICKING_INTERVAL);
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		result = self->priv->last_tick_time;
		return result;
	}
	_tmp1_ = self->priv->_state;
	if (ft_timestamp_is_defined (_tmp1_.started_time)) {
		gint64 elapsed = 0LL;
		gint64 elapsed_rounded = 0LL;
		FtTimerState _tmp2_;
		FtTimerState _tmp3_;
		elapsed = ft_timer_calculate_elapsed (self, timestamp);
		elapsed_rounded = ft_timestamp_round (elapsed, FT_TIMER_TICKING_INTERVAL);
		_tmp2_ = self->priv->_state;
		_tmp3_ = self->priv->_state;
		result = (_tmp2_.started_time + _tmp3_.offset) + elapsed_rounded;
		return result;
	}
	result = timestamp;
	return result;
}

static inline void
ft_timer_ensure_timestamp (FtTimer* self,
                           gint64* timestamp)
{
	g_return_if_fail (self != NULL);
	if (ft_timestamp_is_undefined (*timestamp)) {
		*timestamp = ft_timer_get_current_time (self, FT_TIMESTAMP_UNDEFINED);
	}
}

static gint64
ft_timer_calculate_tick_time (FtTimer* self,
                              gint64 timestamp)
{
	gint64 elapsed = 0LL;
	gint64 elapsed_rounded = 0LL;
	gint64 _tmp0_ = 0LL;
	FtTimerState _tmp1_;
	gint64 result;
	g_return_val_if_fail (self != NULL, -1LL);
	elapsed = ft_timer_calculate_elapsed (self, timestamp);
	elapsed_rounded = ft_timestamp_round (elapsed, FT_TIMER_TICKING_INTERVAL);
	_tmp1_ = self->priv->_state;
	if (ft_timestamp_is_defined (_tmp1_.started_time)) {
		FtTimerState _tmp2_;
		FtTimerState _tmp3_;
		_tmp2_ = self->priv->_state;
		_tmp3_ = self->priv->_state;
		_tmp0_ = (_tmp2_.started_time + _tmp3_.offset) + elapsed_rounded;
	} else {
		_tmp0_ = FT_TIMESTAMP_UNDEFINED;
	}
	result = _tmp0_;
	return result;
}

/**
         * Ticking timeout.
         *
         * Unfortunately it can deviate from full seconds.
         */
static gboolean
_ft_timer_on_timeout_once_gsource_func (gpointer self)
{
	gboolean result;
	result = ft_timer_on_timeout_once ((FtTimer*) self);
	return result;
}

static gboolean
ft_timer_on_timeout (FtTimer* self)
{
	gint64 timestamp = 0LL;
	GSource* _tmp0_;
	gint64 timestamp_rounded = 0LL;
	gint64 remaining = 0LL;
	gboolean _tmp1_ = FALSE;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_vala_return_val_if_fail (self->priv->timeout_id != ((guint) 0), "this.timeout_id != 0", FALSE);
	_tmp0_ = g_main_current_source ();
	timestamp = ft_timer_get_current_time (self, g_source_get_time (_tmp0_));
	timestamp_rounded = ft_timer_calculate_tick_time (self, timestamp);
	remaining = ft_timer_calculate_remaining (self, timestamp);
	if (remaining > ((gint64) 0)) {
		_tmp1_ = self->priv->last_tick_time != timestamp_rounded;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		self->priv->last_tick_time = timestamp_rounded;
		g_signal_emit (self, ft_timer_signals[FT_TIMER_TICK_SIGNAL], 0, timestamp_rounded);
	}
	if (remaining < FT_TIMER_TICKING_TOLERANCE) {
		self->priv->timeout_id = (guint) 0;
		ft_timer_finish (self, timestamp);
		result = G_SOURCE_REMOVE;
		return result;
	}
	if (remaining < (FT_TIMER_TICKING_INTERVAL + FT_TIMER_TICKING_TOLERANCE)) {
		self->priv->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, ft_timestamp_to_milliseconds_uint (remaining), _ft_timer_on_timeout_once_gsource_func, g_object_ref (self), g_object_unref);
		g_source_set_name_by_id (self->priv->timeout_id, "Ft.Timer.on_timeout_once");
		result = G_SOURCE_REMOVE;
		return result;
	}
	result = G_SOURCE_CONTINUE;
	return result;
}

/**
         * Precise timeout.
         *
         * It's meant to set up idle timeout that is aligned to full seconds.
         */
static gboolean
_ft_timer_on_timeout_gsource_func (gpointer self)
{
	gboolean result;
	result = ft_timer_on_timeout ((FtTimer*) self);
	return result;
}

static gboolean
ft_timer_on_timeout_once (FtTimer* self)
{
	gint64 timestamp = 0LL;
	GSource* _tmp0_;
	gint64 timestamp_rounded = 0LL;
	gint64 remaining = 0LL;
	gboolean _tmp1_ = FALSE;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_vala_return_val_if_fail (self->priv->timeout_id != ((guint) 0), "this.timeout_id != 0", FALSE);
	_tmp0_ = g_main_current_source ();
	timestamp = ft_timer_get_current_time (self, g_source_get_time (_tmp0_));
	timestamp_rounded = ft_timer_calculate_tick_time (self, timestamp);
	remaining = ft_timer_calculate_remaining (self, timestamp);
	self->priv->timeout_id = (guint) 0;
	if (remaining > ((gint64) 0)) {
		_tmp1_ = self->priv->last_tick_time != timestamp_rounded;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		self->priv->last_tick_time = timestamp_rounded;
		g_signal_emit (self, ft_timer_signals[FT_TIMER_TICK_SIGNAL], 0, timestamp_rounded);
	}
	if (remaining < FT_TIMER_TICKING_TOLERANCE) {
		ft_timer_finish (self, timestamp);
		result = G_SOURCE_REMOVE;
		return result;
	}
	if (remaining < (FT_TIMER_TICKING_INTERVAL + FT_TIMER_TICKING_TOLERANCE)) {
		self->priv->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, ft_timestamp_to_milliseconds_uint (remaining), _ft_timer_on_timeout_once_gsource_func, g_object_ref (self), g_object_unref);
		g_source_set_name_by_id (self->priv->timeout_id, "Ft.Timer.on_timeout_once");
		result = G_SOURCE_REMOVE;
		return result;
	}
	self->priv->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, ft_timestamp_to_milliseconds_uint (FT_TIMER_TICKING_INTERVAL), _ft_timer_on_timeout_gsource_func, g_object_ref (self), g_object_unref);
	g_source_set_name_by_id (self->priv->timeout_id, "Ft.Timer.on_timeout");
	result = G_SOURCE_REMOVE;
	return result;
}

/**
         * Start ticking. First tick will be emitted after the `interval`.
         *
         * `aligned` will align ticks to elapsed time. It's meant for displaying elapsed/remaining time to sync label
         * updates with the timer.
         */
static void
ft_timer_start_timeout_internal (FtTimer* self,
                                 gint64 timestamp)
{
	gint64 timestamp_rounded = 0LL;
	gint64 remaining = 0LL;
	g_return_if_fail (self != NULL);
	_vala_return_if_fail (ft_timestamp_is_defined (timestamp), "Ft.Timestamp.is_defined (timestamp)");
	_vala_return_if_fail (self->priv->timeout_id == ((guint) 0), "this.timeout_id == 0");
	timestamp_rounded = ft_timer_calculate_tick_time (self, timestamp);
	remaining = ft_timer_calculate_remaining (self, timestamp);
	self->priv->last_tick_time = timestamp_rounded;
	if (remaining > FT_TIMER_TICKING_TOLERANCE) {
		gint64 deviation = 0LL;
		gboolean _tmp0_ = FALSE;
		deviation = timestamp - timestamp_rounded;
		if (remaining > FT_TIMER_TICKING_INTERVAL) {
			_tmp0_ = llabs (deviation) < FT_TIMER_TICKING_TOLERANCE;
		} else {
			_tmp0_ = FALSE;
		}
		if (_tmp0_) {
			self->priv->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, ft_timestamp_to_milliseconds_uint (FT_TIMER_TICKING_INTERVAL), _ft_timer_on_timeout_gsource_func, g_object_ref (self), g_object_unref);
			g_source_set_name_by_id (self->priv->timeout_id, "Ft.Timer.on_timeout");
		} else {
			self->priv->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, ft_timestamp_to_milliseconds_uint (FT_TIMER_TICKING_INTERVAL - deviation), _ft_timer_on_timeout_once_gsource_func, g_object_ref (self), g_object_unref);
			g_source_set_name_by_id (self->priv->timeout_id, "Ft.Timer.on_timeout_once");
		}
	} else {
		ft_timer_finish (self, timestamp);
	}
}

static void
ft_timer_start_timeout (FtTimer* self,
                        gint64 timestamp)
{
	g_return_if_fail (self != NULL);
	if (self->priv->timeout_id != ((guint) 0)) {
		return;
	}
	if (ft_timestamp_is_frozen ()) {
		return;
	}
	ft_timer_synchronize (self, FT_TIMESTAMP_UNDEFINED, timestamp);
	ft_timer_start_timeout_internal (self, timestamp);
}

static void
ft_timer_stop_timeout (FtTimer* self,
                       gint64 timestamp)
{
	gint64 timestamp_rounded = 0LL;
	gboolean _tmp0_ = FALSE;
	g_return_if_fail (self != NULL);
	timestamp_rounded = ft_timer_calculate_tick_time (self, timestamp);
	if (self->priv->last_tick_time != timestamp_rounded) {
		_tmp0_ = timestamp_rounded >= self->priv->last_state_changed_time;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		self->priv->last_tick_time = timestamp_rounded;
		g_signal_emit (self, ft_timer_signals[FT_TIMER_TICK_SIGNAL], 0, timestamp_rounded);
	}
	if (self->priv->timeout_id != ((guint) 0)) {
		g_source_remove (self->priv->timeout_id);
		self->priv->timeout_id = (guint) 0;
	}
	self->priv->monotonic_time_offset = (gint64) 0;
	self->priv->last_tick_time = FT_TIMESTAMP_UNDEFINED;
}

/**
         * Return time of a last state change.
         *
         * It's deliberate that "last_state_changed_time" is not a property, as we don't want emitting
         * notify events for that.
         */
gint64
ft_timer_get_last_state_changed_time (FtTimer* self)
{
	gint64 result;
	g_return_val_if_fail (self != NULL, -1LL);
	result = self->priv->last_state_changed_time;
	return result;
}

gint64
ft_timer_get_last_tick_time (FtTimer* self)
{
	gint64 result;
	g_return_val_if_fail (self != NULL, -1LL);
	result = self->priv->last_tick_time;
	return result;
}

/**
         * Calculate elapsed time.
         *
         * It's only accurate when passing a current time. If you pass a historic time
         * the result will be just an estimate.
         */
gint64
ft_timer_calculate_elapsed (FtTimer* self,
                            gint64 timestamp)
{
	FtTimerState _tmp0_;
	gint64 result;
	g_return_val_if_fail (self != NULL, -1LL);
	_tmp0_ = self->priv->_state;
	if (ft_timestamp_is_undefined (_tmp0_.started_time)) {
		result = (gint64) 0;
		return result;
	}
	ft_timer_ensure_timestamp (self, &timestamp);
	result = ft_timer_state_calculate_elapsed (&self->priv->_state, timestamp);
	return result;
}

/**
         * Calculate remaining time.
         *
         * It's only accurate when passing a current time. If you pass a historic time
         * the result will be just an estimate.
         */
gint64
ft_timer_calculate_remaining (FtTimer* self,
                              gint64 timestamp)
{
	FtTimerState _tmp0_;
	gint64 result;
	g_return_val_if_fail (self != NULL, -1LL);
	_tmp0_ = self->priv->_state;
	result = _tmp0_.duration - ft_timer_calculate_elapsed (self, timestamp);
	return result;
}

/**
         * Calculate progress.
         *
         * It's only accurate when passing a current time. If you pass a historic time
         * the result will be just an estimate.
         */
gdouble
ft_timer_calculate_progress (FtTimer* self,
                             gint64 timestamp)
{
	gdouble elapsed = 0.0;
	gdouble duration = 0.0;
	FtTimerState _tmp0_;
	gdouble _tmp1_ = 0.0;
	gdouble result;
	g_return_val_if_fail (self != NULL, -1.0);
	elapsed = (gdouble) ft_timer_calculate_elapsed (self, timestamp);
	_tmp0_ = self->priv->_state;
	duration = (gdouble) _tmp0_.duration;
	if (duration > 0.0) {
		_tmp1_ = elapsed / duration;
	} else {
		_tmp1_ = 0.0;
	}
	result = _tmp1_;
	return result;
}

/**
         * Calculate finish time.
         *
         * When paused it returns `Timestamp.UNDEFINED`.
         */
gint64
ft_timer_calculate_finish_time (FtTimer* self)
{
	FtTimerState _tmp1_;
	FtTimerState _tmp2_;
	FtTimerState _tmp3_;
	gint64 result;
	g_return_val_if_fail (self != NULL, -1LL);
	if (!ft_timer_is_running (self)) {
		result = FT_TIMESTAMP_UNDEFINED;
		return result;
	}
	if (ft_timer_is_finished (self)) {
		FtTimerState _tmp0_;
		_tmp0_ = self->priv->_state;
		result = _tmp0_.finished_time;
		return result;
	}
	_tmp1_ = self->priv->_state;
	_tmp2_ = self->priv->_state;
	_tmp3_ = self->priv->_state;
	result = (_tmp1_.started_time + _tmp2_.offset) + _tmp3_.duration;
	return result;
}

/**
         * Wait until timer finishes
         *
         * It will only have an effect after Timer.start() or after setting up timer state.
         *
         * Intended for unit tests.
         */
static gpointer
_g_main_context_ref0 (gpointer self)
{
	return self ? g_main_context_ref (self) : NULL;
}

void
ft_timer_run (FtTimer* self,
              GCancellable* cancellable)
{
	GMainContext* main_context = NULL;
	GMainContext* _tmp0_;
	GMainContext* _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = g_main_context_default ();
	_tmp1_ = _g_main_context_ref0 (_tmp0_);
	main_context = _tmp1_;
	while (TRUE) {
		gboolean _tmp2_ = FALSE;
		GMainContext* _tmp4_;
		if (ft_timer_is_running (self)) {
			gboolean _tmp3_ = FALSE;
			if (cancellable == NULL) {
				_tmp3_ = TRUE;
			} else {
				_tmp3_ = !g_cancellable_is_cancelled (cancellable);
			}
			_tmp2_ = _tmp3_;
		} else {
			_tmp2_ = FALSE;
		}
		if (!_tmp2_) {
			break;
		}
		_tmp4_ = main_context;
		g_main_context_iteration (_tmp4_, TRUE);
	}
	_g_main_context_unref0 (main_context);
}

/**
         * Manually perform a tick or check whether timer has finished.
         *
         * Intended for unit tests.
         */
void
ft_timer_iterate (FtTimer* self)
{
	gint64 timestamp = 0LL;
	gint64 timestamp_rounded = 0LL;
	gint64 remaining = 0LL;
	gboolean _tmp0_ = FALSE;
	g_return_if_fail (self != NULL);
	timestamp = ft_timestamp_peek ();
	timestamp_rounded = ft_timer_calculate_tick_time (self, timestamp);
	remaining = ft_timer_calculate_remaining (self, timestamp);
	if (remaining > ((gint64) 0)) {
		_tmp0_ = self->priv->last_tick_time != timestamp_rounded;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		g_signal_emit (self, ft_timer_signals[FT_TIMER_TICK_SIGNAL], 0, timestamp_rounded);
	}
	if (remaining < FT_TIMER_TICKING_TOLERANCE) {
		ft_timer_finish (self, timestamp);
	}
}

static void
ft_timer_real_dispose (GObject* base)
{
	FtTimer * self;
	self = (FtTimer*) base;
	if (self->priv->timeout_id != ((guint) 0)) {
		g_source_remove (self->priv->timeout_id);
		self->priv->timeout_id = (guint) 0;
	}
	if (self->priv->prepare_for_sleep_id != ((gulong) 0)) {
		FtSleepMonitor* _tmp0_;
		_tmp0_ = self->priv->sleep_monitor;
		g_signal_handler_disconnect ((GObject*) _tmp0_, self->priv->prepare_for_sleep_id);
		self->priv->prepare_for_sleep_id = (gulong) 0;
	}
	if (self->priv->woke_up_id != ((gulong) 0)) {
		FtSleepMonitor* _tmp1_;
		_tmp1_ = self->priv->sleep_monitor;
		g_signal_handler_disconnect ((GObject*) _tmp1_, self->priv->woke_up_id);
		self->priv->woke_up_id = (gulong) 0;
	}
	_g_object_unref0 (self->priv->sleep_monitor);
	self->priv->sleep_monitor = NULL;
	G_OBJECT_CLASS (ft_timer_parent_class)->dispose (G_TYPE_CHECK_INSTANCE_CAST (self, G_TYPE_OBJECT, GObject));
}

void
ft_timer_get_state (FtTimer* self,
                    FtTimerState * result)
{
	FtTimerState _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_state;
	*result = _tmp0_;
	return;
}

void
ft_timer_set_state (FtTimer* self,
                    FtTimerState * value)
{
	FtTimerState _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = *value;
	ft_timer_set_state_full (self, &_tmp0_, FT_TIMESTAMP_UNDEFINED);
}

gint64
ft_timer_get_duration (FtTimer* self)
{
	gint64 result;
	FtTimerState _tmp0_;
	g_return_val_if_fail (self != NULL, -1LL);
	_tmp0_ = self->priv->_state;
	result = _tmp0_.duration;
	return result;
}

void
ft_timer_set_duration (FtTimer* self,
                       gint64 value)
{
	g_return_if_fail (self != NULL);
	ft_timer_set_duration_full (self, value, FT_TIMESTAMP_UNDEFINED);
}

gint64
ft_timer_get_started_time (FtTimer* self)
{
	gint64 result;
	FtTimerState _tmp0_;
	g_return_val_if_fail (self != NULL, -1LL);
	_tmp0_ = self->priv->_state;
	result = _tmp0_.started_time;
	return result;
}

gint64
ft_timer_get_offset (FtTimer* self)
{
	gint64 result;
	FtTimerState _tmp0_;
	g_return_val_if_fail (self != NULL, -1LL);
	_tmp0_ = self->priv->_state;
	result = _tmp0_.offset;
	return result;
}

void*
ft_timer_get_user_data (FtTimer* self)
{
	void* result;
	FtTimerState _tmp0_;
	void* _tmp1_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_state;
	_tmp1_ = _tmp0_.user_data;
	result = _tmp1_;
	return result;
}

void
ft_timer_set_user_data (FtTimer* self,
                        void* value)
{
	FtTimerState _tmp0_;
	void* _tmp1_;
	FtTimerState new_state = {0};
	FtTimerState _tmp2_ = {0};
	FtTimerState _tmp3_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_state;
	_tmp1_ = _tmp0_.user_data;
	if (value == _tmp1_) {
		return;
	}
	if (ft_timer_is_finished (self)) {
		g_debug ("timer.vala:281: Trying to set timer user-data after it finished");
	}
	ft_timer_state_copy (&self->priv->_state, &_tmp2_);
	new_state = _tmp2_;
	new_state.user_data = value;
	_tmp3_ = new_state;
	ft_timer_set_state (self, &_tmp3_);
}

static void
ft_timer_real_resolve_state (FtTimer* self,
                             FtTimerState* state,
                             gint64 timestamp)
{
	FtTimerState _tmp0_;
	gboolean _tmp1_ = FALSE;
	FtTimerState _tmp2_;
	gboolean _tmp6_ = FALSE;
	FtTimerState _tmp7_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (state != NULL);
	_tmp0_ = *state;
	if (ft_timestamp_is_undefined (_tmp0_.started_time)) {
		(*state).paused_time = FT_TIMESTAMP_UNDEFINED;
		(*state).finished_time = FT_TIMESTAMP_UNDEFINED;
	}
	_tmp2_ = *state;
	if (ft_timestamp_is_defined (_tmp2_.paused_time)) {
		FtTimerState _tmp3_;
		FtTimerState _tmp4_;
		_tmp3_ = *state;
		_tmp4_ = *state;
		_tmp1_ = _tmp3_.paused_time < _tmp4_.started_time;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		FtTimerState _tmp5_;
		_tmp5_ = *state;
		(*state).paused_time = _tmp5_.started_time;
	}
	_tmp7_ = *state;
	if (ft_timestamp_is_defined (_tmp7_.finished_time)) {
		FtTimerState _tmp8_;
		FtTimerState _tmp9_;
		_tmp8_ = *state;
		_tmp9_ = *state;
		_tmp6_ = _tmp8_.finished_time < _tmp9_.started_time;
	} else {
		_tmp6_ = FALSE;
	}
	if (_tmp6_) {
		FtTimerState _tmp10_;
		_tmp10_ = *state;
		(*state).finished_time = _tmp10_.started_time;
	}
}

static void
g_cclosure_user_marshal_VOID__POINTER_INT64 (GClosure * closure,
                                             GValue * return_value,
                                             guint n_param_values,
                                             const GValue * param_values,
                                             gpointer invocation_hint,
                                             gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__POINTER_INT64) (gpointer data1, gpointer arg_1, gint64 arg_2, gpointer data2);
	register GMarshalFunc_VOID__POINTER_INT64 callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 3);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_VOID__POINTER_INT64) (marshal_data ? marshal_data : cc->callback);
	callback (data1, g_value_get_pointer (param_values + 1), g_value_get_int64 (param_values + 2), data2);
}

static void
ft_timer_real_state_changed (FtTimer* self,
                             const FtTimerState* current_state,
                             const FtTimerState* previous_state)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	g_return_if_fail (self != NULL);
	g_return_if_fail (current_state != NULL);
	g_return_if_fail (previous_state != NULL);
	if (ft_timer_state_is_running (current_state)) {
		ft_timer_start_timeout (self, self->priv->last_state_changed_time);
	} else {
		ft_timer_stop_timeout (self, self->priv->last_state_changed_time);
	}
	if (ft_timer_state_is_finished (current_state)) {
		_tmp1_ = ft_timer_state_is_started (previous_state);
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		_tmp0_ = !ft_timer_state_is_finished (previous_state);
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		FtTimerState _tmp2_;
		_tmp2_ = *current_state;
		g_signal_emit (self, ft_timer_signals[FT_TIMER_FINISHED_SIGNAL], 0, &_tmp2_);
	}
}

static void
g_cclosure_user_marshal_VOID__BOXED_BOXED (GClosure * closure,
                                           GValue * return_value,
                                           guint n_param_values,
                                           const GValue * param_values,
                                           gpointer invocation_hint,
                                           gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__BOXED_BOXED) (gpointer data1, gpointer arg_1, gpointer arg_2, gpointer data2);
	register GMarshalFunc_VOID__BOXED_BOXED callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 3);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_VOID__BOXED_BOXED) (marshal_data ? marshal_data : cc->callback);
	callback (data1, g_value_get_boxed (param_values + 1), g_value_get_boxed (param_values + 2), data2);
}

static void
ft_timer_real_tick (FtTimer* self,
                    gint64 timestamp)
{
	g_return_if_fail (self != NULL);
	self->priv->last_tick_time = timestamp;
}

static void
g_cclosure_user_marshal_VOID__INT64 (GClosure * closure,
                                     GValue * return_value,
                                     guint n_param_values,
                                     const GValue * param_values,
                                     gpointer invocation_hint,
                                     gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__INT64) (gpointer data1, gint64 arg_1, gpointer data2);
	register GMarshalFunc_VOID__INT64 callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 2);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_VOID__INT64) (marshal_data ? marshal_data : cc->callback);
	callback (data1, g_value_get_int64 (param_values + 1), data2);
}

static void
ft_timer_real_suspended (FtTimer* self,
                         gint64 start_time,
                         gint64 end_time)
{
	g_return_if_fail (self != NULL);
	if (self->priv->last_state_changed_time > start_time) {
		return;
	}
	if (ft_timer_is_running (self)) {
		FtTimerState new_state = {0};
		FtTimerState _tmp0_ = {0};
		FtTimerState _tmp1_;
		ft_timer_state_copy (&self->priv->_state, &_tmp0_);
		new_state = _tmp0_;
		new_state.offset = new_state.offset + (end_time - start_time);
		_tmp1_ = new_state;
		ft_timer_set_state_full (self, &_tmp1_, end_time);
	}
}

static void
g_cclosure_user_marshal_VOID__INT64_INT64 (GClosure * closure,
                                           GValue * return_value,
                                           guint n_param_values,
                                           const GValue * param_values,
                                           gpointer invocation_hint,
                                           gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__INT64_INT64) (gpointer data1, gint64 arg_1, gint64 arg_2, gpointer data2);
	register GMarshalFunc_VOID__INT64_INT64 callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 3);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_VOID__INT64_INT64) (marshal_data ? marshal_data : cc->callback);
	callback (data1, g_value_get_int64 (param_values + 1), g_value_get_int64 (param_values + 2), data2);
}

static void
_ft_timer___lambda29_ (FtTimer* self)
{
	self->priv->suspend_time = ft_timer_get_current_time (self, FT_TIMESTAMP_UNDEFINED);
	ft_timer_stop_timeout (self, self->priv->suspend_time);
	g_signal_emit (self, ft_timer_signals[FT_TIMER_SUSPENDING_SIGNAL], 0, self->priv->suspend_time);
}

static void
__ft_timer___lambda29__ft_sleep_monitor_prepare_for_sleep (FtSleepMonitor* _sender,
                                                           gpointer self)
{
	_ft_timer___lambda29_ ((FtTimer*) self);
}

static void
_ft_timer___lambda30_ (FtTimer* self)
{
	gint64 timestamp = 0LL;
	timestamp = ft_timestamp_from_now ();
	if (ft_timer_is_running (self)) {
		ft_timer_synchronize (self, FT_TIMESTAMP_UNDEFINED, timestamp);
	}
	g_signal_emit (self, ft_timer_signals[FT_TIMER_SUSPENDED_SIGNAL], 0, self->priv->suspend_time, timestamp);
	self->priv->suspend_time = FT_TIMESTAMP_UNDEFINED;
}

static void
__ft_timer___lambda30__ft_sleep_monitor_woke_up (FtSleepMonitor* _sender,
                                                 gpointer self)
{
	_ft_timer___lambda30_ ((FtTimer*) self);
}

static GObject *
ft_timer_constructor (GType type,
                      guint n_construct_properties,
                      GObjectConstructParam * construct_properties)
{
	GObject * obj;
	GObjectClass * parent_class;
	FtTimer * self;
	FtSleepMonitor* _tmp0_;
	FtSleepMonitor* _tmp1_;
	gulong _tmp2_;
	FtSleepMonitor* _tmp3_;
	gulong _tmp4_;
	parent_class = G_OBJECT_CLASS (ft_timer_parent_class);
	obj = parent_class->constructor (type, n_construct_properties, construct_properties);
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, FT_TYPE_TIMER, FtTimer);
	_tmp0_ = ft_sleep_monitor_new ();
	_g_object_unref0 (self->priv->sleep_monitor);
	self->priv->sleep_monitor = _tmp0_;
	_tmp1_ = self->priv->sleep_monitor;
	_tmp2_ = g_signal_connect_object (_tmp1_, "prepare-for-sleep", (GCallback) __ft_timer___lambda29__ft_sleep_monitor_prepare_for_sleep, self, 0);
	self->priv->prepare_for_sleep_id = _tmp2_;
	_tmp3_ = self->priv->sleep_monitor;
	_tmp4_ = g_signal_connect_object (_tmp3_, "woke-up", (GCallback) __ft_timer___lambda30__ft_sleep_monitor_woke_up, self, 0);
	self->priv->woke_up_id = _tmp4_;
	return obj;
}

static void
ft_timer_class_init (FtTimerClass * klass,
                     gpointer klass_data)
{
	ft_timer_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &FtTimer_private_offset);
	((GObjectClass *) klass)->dispose = (void (*) (GObject*)) ft_timer_real_dispose;
	G_OBJECT_CLASS (klass)->get_property = _vala_ft_timer_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_ft_timer_set_property;
	G_OBJECT_CLASS (klass)->constructor = ft_timer_constructor;
	G_OBJECT_CLASS (klass)->finalize = ft_timer_finalize;
	/**
	         * Timer internal state.
	         *
	         * You should not change its fields directly.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_TIMER_STATE_PROPERTY, ft_timer_properties[FT_TIMER_STATE_PROPERTY] = g_param_spec_boxed ("state", "state", "state", FT_TYPE_TIMER_STATE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_EXPLICIT_NOTIFY));
	/**
	         * The intended duration of the state, not counting gaps/interruptions.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_TIMER_DURATION_PROPERTY, ft_timer_properties[FT_TIMER_DURATION_PROPERTY] = g_param_spec_int64 ("duration", "duration", "duration", G_MININT64, G_MAXINT64, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_EXPLICIT_NOTIFY));
	/**
	         * Time when timer has been initialized/started.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_TIMER_STARTED_TIME_PROPERTY, ft_timer_properties[FT_TIMER_STARTED_TIME_PROPERTY] = g_param_spec_int64 ("started-time", "started-time", "started-time", G_MININT64, G_MAXINT64, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY));
	/**
	         * Time lost during previous pauses. If pause is ongoing its not counted here yet.
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_TIMER_OFFSET_PROPERTY, ft_timer_properties[FT_TIMER_OFFSET_PROPERTY] = g_param_spec_int64 ("offset", "offset", "offset", G_MININT64, G_MAXINT64, 0, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY));
	/**
	         * Extra data associated with current state
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_TIMER_USER_DATA_PROPERTY, ft_timer_properties[FT_TIMER_USER_DATA_PROPERTY] = g_param_spec_pointer ("user-data", "user-data", "user-data", G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_EXPLICIT_NOTIFY));
	/**
	         * Emitted before setting a new state.
	         *
	         * It allows for fine-tuning the state before emitting state-changed signal.
	         * Default handler ensures that state is valid.
	         */
	ft_timer_signals[FT_TIMER_RESOLVE_STATE_SIGNAL] = g_signal_new_class_handler ("resolve-state", FT_TYPE_TIMER, G_SIGNAL_RUN_LAST, (GCallback) ft_timer_real_resolve_state, NULL, NULL, g_cclosure_user_marshal_VOID__POINTER_INT64, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_INT64);
	/**
	         * Emitted on any state related changes. Default handler acknowledges the change.
	         */
	ft_timer_signals[FT_TIMER_STATE_CHANGED_SIGNAL] = g_signal_new_class_handler ("state-changed", FT_TYPE_TIMER, G_SIGNAL_RUN_LAST, (GCallback) ft_timer_real_state_changed, NULL, NULL, g_cclosure_user_marshal_VOID__BOXED_BOXED, G_TYPE_NONE, 2, FT_TYPE_TIMER_STATE, FT_TYPE_TIMER_STATE);
	/**
	         * Emitted every second when timer is running.
	         *
	         * Ticks are aligned to full seconds of elapsed time.
	         */
	ft_timer_signals[FT_TIMER_TICK_SIGNAL] = g_signal_new_class_handler ("tick", FT_TYPE_TIMER, G_SIGNAL_RUN_FIRST, (GCallback) ft_timer_real_tick, NULL, NULL, g_cclosure_user_marshal_VOID__INT64, G_TYPE_NONE, 1, G_TYPE_INT64);
	/**
	         * Emitted when countdown is close to zero or passed it.
	         */
	ft_timer_signals[FT_TIMER_FINISHED_SIGNAL] = g_signal_new ("finished", FT_TYPE_TIMER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, FT_TYPE_TIMER_STATE);
	/**
	         * Emitted after synchronizing timer against monotonic time.
	         */
	ft_timer_signals[FT_TIMER_SYNCHRONIZED_SIGNAL] = g_signal_new ("synchronized", FT_TYPE_TIMER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	/**
	         * Emitted before system has suspended.
	         *
	         * It's emitted even when timer is not running.
	         */
	ft_timer_signals[FT_TIMER_SUSPENDING_SIGNAL] = g_signal_new ("suspending", FT_TYPE_TIMER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__INT64, G_TYPE_NONE, 1, G_TYPE_INT64);
	/**
	         * Emitted right after system wakes up and the timer has been synchronised.
	         *
	         * It's emitted even when the timer is not running.
	         */
	ft_timer_signals[FT_TIMER_SUSPENDED_SIGNAL] = g_signal_new_class_handler ("suspended", FT_TYPE_TIMER, G_SIGNAL_RUN_LAST, (GCallback) ft_timer_real_suspended, NULL, NULL, g_cclosure_user_marshal_VOID__INT64_INT64, G_TYPE_NONE, 2, G_TYPE_INT64, G_TYPE_INT64);
}

static void
ft_timer_instance_init (FtTimer * self,
                        gpointer klass)
{
	self->priv = ft_timer_get_instance_private (self);
	ft_timer_state_init (&self->priv->_state);
	self->priv->timeout_id = (guint) 0;
	self->priv->last_state_changed_time = FT_TIMESTAMP_UNDEFINED;
	self->priv->last_tick_time = FT_TIMESTAMP_UNDEFINED;
	self->priv->suspend_time = FT_TIMESTAMP_UNDEFINED;
	self->priv->resolving_state = FALSE;
	self->priv->changing_state = 0;
	self->priv->state_to_resolve = NULL;
	self->priv->monotonic_time_offset = (gint64) 0;
	self->priv->prepare_for_sleep_id = (gulong) 0;
	self->priv->woke_up_id = (gulong) 0;
}

static void
ft_timer_finalize (GObject * obj)
{
	FtTimer * self;
	FtTimer* _tmp0_;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, FT_TYPE_TIMER, FtTimer);
	_tmp0_ = ft_timer_instance;
	if (_tmp0_ == NULL) {
		_g_object_unref0 (ft_timer_instance);
		ft_timer_instance = NULL;
	}
	_ft_timer_state_free0 (self->priv->state_to_resolve);
	_g_object_unref0 (self->priv->sleep_monitor);
	G_OBJECT_CLASS (ft_timer_parent_class)->finalize (obj);
}

/**
     * Timer class mimics a physical countdown timer.
     *
     * It trigger events on state changes. To trigger ticking event at regular intervals use TimerTicker.
     */
static GType
ft_timer_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (FtTimerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ft_timer_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (FtTimer), 0, (GInstanceInitFunc) ft_timer_instance_init, NULL };
	GType ft_timer_type_id;
	ft_timer_type_id = g_type_register_static (G_TYPE_OBJECT, "FtTimer", &g_define_type_info, 0);
	FtTimer_private_offset = g_type_add_instance_private (ft_timer_type_id, sizeof (FtTimerPrivate));
	return ft_timer_type_id;
}

GType
ft_timer_get_type (void)
{
	static volatile gsize ft_timer_type_id__once = 0;
	if (g_once_init_enter (&ft_timer_type_id__once)) {
		GType ft_timer_type_id;
		ft_timer_type_id = ft_timer_get_type_once ();
		g_once_init_leave (&ft_timer_type_id__once, ft_timer_type_id);
	}
	return ft_timer_type_id__once;
}

static void
_vala_ft_timer_get_property (GObject * object,
                             guint property_id,
                             GValue * value,
                             GParamSpec * pspec)
{
	FtTimer * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, FT_TYPE_TIMER, FtTimer);
	switch (property_id) {
		case FT_TIMER_STATE_PROPERTY:
		{
			FtTimerState boxed;
			ft_timer_get_state (self, &boxed);
			g_value_set_boxed (value, &boxed);
		}
		break;
		case FT_TIMER_DURATION_PROPERTY:
		g_value_set_int64 (value, ft_timer_get_duration (self));
		break;
		case FT_TIMER_STARTED_TIME_PROPERTY:
		g_value_set_int64 (value, ft_timer_get_started_time (self));
		break;
		case FT_TIMER_OFFSET_PROPERTY:
		g_value_set_int64 (value, ft_timer_get_offset (self));
		break;
		case FT_TIMER_USER_DATA_PROPERTY:
		g_value_set_pointer (value, ft_timer_get_user_data (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_ft_timer_set_property (GObject * object,
                             guint property_id,
                             const GValue * value,
                             GParamSpec * pspec)
{
	FtTimer * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, FT_TYPE_TIMER, FtTimer);
	switch (property_id) {
		case FT_TIMER_STATE_PROPERTY:
		ft_timer_set_state (self, g_value_get_boxed (value));
		break;
		case FT_TIMER_DURATION_PROPERTY:
		ft_timer_set_duration (self, g_value_get_int64 (value));
		break;
		case FT_TIMER_USER_DATA_PROPERTY:
		ft_timer_set_user_data (self, g_value_get_pointer (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

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;
}

