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

/*
 * Copyright (c) 2023-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 <float.h>
#include <math.h>
#include <glib-object.h>

#define FT_SCHEDULER_MAX_ITERATIONS ((guint) 100)
#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_free0(var) (var = (g_free (var), NULL))
#define _g_variant_builder_unref0(var) ((var == NULL) ? NULL : (var = (g_variant_builder_unref (var), NULL)))
#define _g_string_free0(var) ((var == NULL) ? NULL : (var = (g_string_free (var, TRUE), NULL)))
enum  {
	FT_SCHEDULER_0_PROPERTY,
	FT_SCHEDULER_SESSION_TEMPLATE_PROPERTY,
	FT_SCHEDULER_NUM_PROPERTIES
};
static GParamSpec* ft_scheduler_properties[FT_SCHEDULER_NUM_PROPERTIES];
typedef struct _Block38Data Block38Data;
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
enum  {
	FT_SIMPLE_SCHEDULER_0_PROPERTY,
	FT_SIMPLE_SCHEDULER_NUM_PROPERTIES
};
static GParamSpec* ft_simple_scheduler_properties[FT_SIMPLE_SCHEDULER_NUM_PROPERTIES];
typedef struct _Block39Data Block39Data;
#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 _FtSchedulerPrivate {
	FtSessionTemplate _session_template;
};

struct _Block38Data {
	int _ref_count_;
	FtScheduler* self;
	gint64 remaining_elapsed;
	gint64 reference_time;
};

struct _FtSimpleSchedulerPrivate {
	gdouble MAX_SCORE;
	gint64 EXTRA_SCORE_THRESHOLD;
};

struct _Block39Data {
	int _ref_count_;
	FtSimpleScheduler* self;
	gint64 range_start;
	gint64 elapsed;
	gint64 timestamp;
};

static gint FtScheduler_private_offset;
static gpointer ft_scheduler_parent_class = NULL;
static gint FtSimpleScheduler_private_offset;
static gpointer ft_simple_scheduler_parent_class = NULL;

static Block38Data* block38_data_ref (Block38Data* _data38_);
static void block38_data_unref (void * _userdata_);
static void __lambda31_ (Block38Data* _data38_,
                  FtGap* gap);
static void ___lambda31__gfunc (gconstpointer data,
                         gpointer self);
static gdouble ft_scheduler_real_calculate_time_block_score (FtScheduler* self,
                                                      FtTimeBlock* time_block,
                                                      gint64 timestamp);
static gdouble ft_scheduler_real_calculate_time_block_weight (FtScheduler* self,
                                                       FtTimeBlock* time_block);
static void ft_scheduler_real_resolve_context (FtScheduler* self,
                                        FtTimeBlock* time_block,
                                        gboolean is_resuming,
                                        gint64 timestamp,
                                        FtSchedulerContext* context);
static FtState ft_scheduler_real_resolve_state (FtScheduler* self,
                                         FtSchedulerContext* context);
static FtTimeBlock* ft_scheduler_real_resolve_time_block (FtScheduler* self,
                                                   FtSchedulerContext* context);
static gboolean ft_scheduler_real_is_time_block_completed (FtScheduler* self,
                                                    FtTimeBlock* time_block,
                                                    gint64 timestamp);
VALA_EXTERN void ft_scheduler_build_scheduler_context (FtScheduler* self,
                                           FtSession* session,
                                           gboolean is_resuming,
                                           gint64 timestamp,
                                           FtSchedulerContext* context,
                                           GList** first_scheduled_link);
VALA_EXTERN void ft_session_remove_link (FtSession* self,
                             GList* link);
VALA_EXTERN void ft_session_emit_added (FtSession* self,
                            FtTimeBlock* time_block);
VALA_EXTERN void ft_session_remove_links_after (FtSession* self,
                                    GList* link);
static void __lambda32_ (FtScheduler* self,
                  FtTimeBlock* time_block);
static void ___lambda32__gfunc (gconstpointer data,
                         gpointer self);
static void ft_scheduler_finalize (GObject * obj);
static GType ft_scheduler_get_type_once (void);
static void _vala_ft_scheduler_get_property (GObject * object,
                                      guint property_id,
                                      GValue * value,
                                      GParamSpec * pspec);
static void _vala_ft_scheduler_set_property (GObject * object,
                                      guint property_id,
                                      const GValue * value,
                                      GParamSpec * pspec);
static gint64 ft_simple_scheduler_calculate_time_block_elapsed_at (FtSimpleScheduler* self,
                                                            FtTimeBlock* time_block,
                                                            gint64 timestamp);
static Block39Data* block39_data_ref (Block39Data* _data39_);
static void block39_data_unref (void * _userdata_);
static void __lambda58_ (Block39Data* _data39_,
                  FtGap* gap);
static void ___lambda58__gfunc (gconstpointer data,
                         gpointer self);
static gdouble ft_simple_scheduler_calculate_time_block_score_internal (FtSimpleScheduler* self,
                                                                 FtTimeBlock* time_block,
                                                                 gboolean include_uncompleted_gaps,
                                                                 gint64 timestamp);
static gdouble ft_simple_scheduler_real_calculate_time_block_score (FtScheduler* base,
                                                             FtTimeBlock* time_block,
                                                             gint64 timestamp);
static gdouble ft_simple_scheduler_real_calculate_time_block_weight (FtScheduler* base,
                                                              FtTimeBlock* time_block);
static void ft_simple_scheduler_real_resolve_context (FtScheduler* base,
                                               FtTimeBlock* time_block,
                                               gboolean is_resuming,
                                               gint64 timestamp,
                                               FtSchedulerContext* context);
static FtState ft_simple_scheduler_real_resolve_state (FtScheduler* base,
                                                FtSchedulerContext* context);
static FtTimeBlock* ft_simple_scheduler_real_resolve_time_block (FtScheduler* base,
                                                          FtSchedulerContext* context);
static gboolean ft_simple_scheduler_real_is_time_block_completed (FtScheduler* base,
                                                           FtTimeBlock* time_block,
                                                           gint64 timestamp);
static void ft_simple_scheduler_finalize (GObject * obj);
static GType ft_simple_scheduler_get_type_once (void);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

void
ft_scheduler_context_init (FtSchedulerContext *self)
{
	memset (self, 0, sizeof (FtSchedulerContext));
	(*self).timestamp = FT_TIMESTAMP_UNDEFINED;
	(*self).state = FT_STATE_STOPPED;
	(*self).is_session_completed = FALSE;
	(*self).needs_long_break = FALSE;
	(*self).score = 0.0;
}

void
ft_scheduler_context_initial (gint64 timestamp,
                              FtSchedulerContext* result)
{
	FtSchedulerContext _tmp0_ = {0};
	ft_ensure_timestamp (&timestamp);
	ft_scheduler_context_init (&_tmp0_);
	_tmp0_.timestamp = timestamp;
	*result = _tmp0_;
	return;
}

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

/**
         * Convert structure to Variant.
         *
         * Used in tests.
         */
GVariant*
ft_scheduler_context_to_variant (FtSchedulerContext *self)
{
	GVariantBuilder* builder = NULL;
	GVariantType* _tmp0_;
	GVariantType* _tmp1_;
	GVariantBuilder* _tmp2_;
	GVariantBuilder* _tmp3_;
	GVariant* _tmp4_;
	GVariant* _tmp5_;
	gchar* _tmp6_;
	gchar* _tmp7_;
	GVariant* _tmp8_;
	GVariant* _tmp9_;
	GVariant* _tmp10_;
	GVariant* _tmp11_;
	GVariant* _tmp12_;
	GVariant* _tmp13_;
	GVariant* _tmp14_;
	GVariant* _tmp15_;
	GVariant* _tmp16_;
	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).timestamp);
	g_variant_ref_sink (_tmp4_);
	_tmp5_ = _tmp4_;
	g_variant_builder_add (builder, "{sv}", "timestamp", _tmp5_, NULL);
	_g_variant_unref0 (_tmp5_);
	_tmp6_ = ft_state_to_string ((*self).state);
	_tmp7_ = _tmp6_;
	_tmp8_ = g_variant_new_string (_tmp7_);
	g_variant_ref_sink (_tmp8_);
	_tmp9_ = _tmp8_;
	g_variant_builder_add (builder, "{sv}", "state", _tmp9_, NULL);
	_g_variant_unref0 (_tmp9_);
	_g_free0 (_tmp7_);
	_tmp10_ = g_variant_new_boolean ((*self).is_session_completed);
	g_variant_ref_sink (_tmp10_);
	_tmp11_ = _tmp10_;
	g_variant_builder_add (builder, "{sv}", "is_session_completed", _tmp11_, NULL);
	_g_variant_unref0 (_tmp11_);
	_tmp12_ = g_variant_new_boolean ((*self).needs_long_break);
	g_variant_ref_sink (_tmp12_);
	_tmp13_ = _tmp12_;
	g_variant_builder_add (builder, "{sv}", "needs_long_break", _tmp13_, NULL);
	_g_variant_unref0 (_tmp13_);
	_tmp14_ = g_variant_new_double ((*self).score);
	g_variant_ref_sink (_tmp14_);
	_tmp15_ = _tmp14_;
	g_variant_builder_add (builder, "{sv}", "score", _tmp15_, NULL);
	_g_variant_unref0 (_tmp15_);
	_tmp16_ = g_variant_builder_end (builder);
	g_variant_ref_sink (_tmp16_);
	result = _tmp16_;
	_g_variant_builder_unref0 (builder);
	return result;
}

/**
         * Represent context as string.
         *
         * Used in tests.
         */
static const gchar*
string_to_string (const gchar* self)
{
	const gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	result = self;
	return result;
}

static gchar*
bool_to_string (gboolean self)
{
	gchar* result;
	if (self) {
		gchar* _tmp0_;
		_tmp0_ = g_strdup ("true");
		result = _tmp0_;
		return result;
	} else {
		gchar* _tmp1_;
		_tmp1_ = g_strdup ("false");
		result = _tmp1_;
		return result;
	}
}

static gchar*
double_to_string (gdouble self)
{
	gchar* _tmp0_;
	gchar* _tmp1_;
	gint _tmp1__length1;
	const gchar* _tmp2_;
	gchar* _tmp3_;
	gchar* _tmp4_;
	gchar* result;
	_tmp0_ = g_new0 (gchar, G_ASCII_DTOSTR_BUF_SIZE);
	_tmp1_ = _tmp0_;
	_tmp1__length1 = G_ASCII_DTOSTR_BUF_SIZE;
	_tmp2_ = g_ascii_dtostr (_tmp1_, (gint) G_ASCII_DTOSTR_BUF_SIZE, self);
	_tmp3_ = g_strdup (_tmp2_);
	_tmp4_ = _tmp3_;
	_tmp1_ = (g_free (_tmp1_), NULL);
	result = _tmp4_;
	return result;
}

gchar*
ft_scheduler_context_to_representation (FtSchedulerContext *self)
{
	gchar* state_string = NULL;
	gchar* _tmp0_;
	GString* representation = NULL;
	GString* _tmp1_;
	gchar* _tmp2_;
	gchar* _tmp3_;
	gchar* _tmp4_;
	gchar* _tmp5_;
	const gchar* _tmp6_;
	gchar* _tmp7_;
	gchar* _tmp8_;
	gchar* _tmp9_;
	gchar* _tmp10_;
	gchar* _tmp11_;
	gchar* _tmp12_;
	gchar* _tmp13_;
	gchar* _tmp14_;
	gchar* _tmp15_;
	gchar* _tmp16_;
	gchar* _tmp17_;
	gchar* _tmp18_;
	gchar* _tmp19_;
	gchar* _tmp20_;
	const gchar* _tmp21_;
	gchar* _tmp22_;
	gchar* result;
	_tmp0_ = ft_state_to_string ((*self).state);
	state_string = _tmp0_;
	_tmp1_ = g_string_new ("SchedulerContext (\n");
	representation = _tmp1_;
	_tmp2_ = g_strdup_printf ("%" G_GINT64_FORMAT, (*self).timestamp);
	_tmp3_ = _tmp2_;
	_tmp4_ = g_strconcat ("    timestamp = ", _tmp3_, ",\n", NULL);
	_tmp5_ = _tmp4_;
	g_string_append (representation, _tmp5_);
	_g_free0 (_tmp5_);
	_g_free0 (_tmp3_);
	_tmp6_ = string_to_string (state_string);
	_tmp7_ = g_strconcat ("    state = ", _tmp6_, ",\n", NULL);
	_tmp8_ = _tmp7_;
	g_string_append (representation, _tmp8_);
	_g_free0 (_tmp8_);
	_tmp9_ = bool_to_string ((*self).is_session_completed);
	_tmp10_ = _tmp9_;
	_tmp11_ = g_strconcat ("    is_session_completed = ", _tmp10_, ",\n", NULL);
	_tmp12_ = _tmp11_;
	g_string_append (representation, _tmp12_);
	_g_free0 (_tmp12_);
	_g_free0 (_tmp10_);
	_tmp13_ = bool_to_string ((*self).needs_long_break);
	_tmp14_ = _tmp13_;
	_tmp15_ = g_strconcat ("    needs_long_break = ", _tmp14_, ",\n", NULL);
	_tmp16_ = _tmp15_;
	g_string_append (representation, _tmp16_);
	_g_free0 (_tmp16_);
	_g_free0 (_tmp14_);
	_tmp17_ = double_to_string ((*self).score);
	_tmp18_ = _tmp17_;
	_tmp19_ = g_strconcat ("    score = ", _tmp18_, ",\n", NULL);
	_tmp20_ = _tmp19_;
	g_string_append (representation, _tmp20_);
	_g_free0 (_tmp20_);
	_g_free0 (_tmp18_);
	g_string_append (representation, ")");
	_tmp21_ = representation->str;
	_tmp22_ = g_strdup (_tmp21_);
	result = _tmp22_;
	_g_string_free0 (representation);
	_g_free0 (state_string);
	return result;
}

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

void
ft_scheduler_context_free (FtSchedulerContext* self)
{
	g_free (self);
}

static GType
ft_scheduler_context_get_type_once (void)
{
	GType ft_scheduler_context_type_id;
	ft_scheduler_context_type_id = g_boxed_type_register_static ("FtSchedulerContext", (GBoxedCopyFunc) ft_scheduler_context_dup, (GBoxedFreeFunc) ft_scheduler_context_free);
	return ft_scheduler_context_type_id;
}

GType
ft_scheduler_context_get_type (void)
{
	static volatile gsize ft_scheduler_context_type_id__once = 0;
	if (g_once_init_enter (&ft_scheduler_context_type_id__once)) {
		GType ft_scheduler_context_type_id;
		ft_scheduler_context_type_id = ft_scheduler_context_get_type_once ();
		g_once_init_leave (&ft_scheduler_context_type_id__once, ft_scheduler_context_type_id);
	}
	return ft_scheduler_context_type_id__once;
}

static inline gpointer
ft_scheduler_get_instance_private (FtScheduler* self)
{
	return G_STRUCT_MEMBER_P (self, FtScheduler_private_offset);
}

static Block38Data*
block38_data_ref (Block38Data* _data38_)
{
	g_atomic_int_inc (&_data38_->_ref_count_);
	return _data38_;
}

static void
block38_data_unref (void * _userdata_)
{
	Block38Data* _data38_;
	_data38_ = (Block38Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data38_->_ref_count_)) {
		FtScheduler* self;
		self = _data38_->self;
		_g_object_unref0 (self);
		g_slice_free (Block38Data, _data38_);
	}
}

static void
__lambda31_ (Block38Data* _data38_,
             FtGap* gap)
{
	FtScheduler* self;
	gint64 _tmp0_;
	gint64 _tmp1_;
	gint64 tmp = 0LL;
	gint64 _tmp2_;
	gint64 _tmp3_;
	self = _data38_->self;
	g_return_if_fail (gap != NULL);
	_tmp0_ = ft_schedulable_get_end_time ((FtSchedulable*) gap);
	_tmp1_ = _tmp0_;
	if (ft_timestamp_is_undefined (_tmp1_)) {
		return;
	}
	_tmp2_ = ft_schedulable_get_start_time ((FtSchedulable*) gap);
	_tmp3_ = _tmp2_;
	tmp = _data38_->remaining_elapsed - (_tmp3_ - _data38_->reference_time);
	if (tmp > ((gint64) 0)) {
		gint64 _tmp4_;
		gint64 _tmp5_;
		_data38_->remaining_elapsed = tmp;
		_tmp4_ = ft_schedulable_get_end_time ((FtSchedulable*) gap);
		_tmp5_ = _tmp4_;
		_data38_->reference_time = _tmp5_;
	}
}

static void
___lambda31__gfunc (gconstpointer data,
                    gpointer self)
{
	__lambda31_ (self, (FtGap*) data);
}

gint64
ft_scheduler_calculate_time_block_completion_time (FtScheduler* self,
                                                   FtTimeBlock* time_block)
{
	Block38Data* _data38_;
	gint64 _tmp0_;
	gint64 _tmp1_;
	gint64 intended_duration = 0LL;
	gint64 _tmp4_ = 0LL;
	FtState _tmp5_;
	FtState _tmp6_;
	gint64 completion_threshold = 0LL;
	gint64 _tmp8_;
	gint64 _tmp9_;
	gint64 result;
	g_return_val_if_fail (self != NULL, -1LL);
	g_return_val_if_fail (time_block != NULL, -1LL);
	_data38_ = g_slice_new0 (Block38Data);
	_data38_->_ref_count_ = 1;
	_data38_->self = g_object_ref (self);
	_tmp0_ = ft_schedulable_get_start_time ((FtSchedulable*) time_block);
	_tmp1_ = _tmp0_;
	if (ft_timestamp_is_undefined (_tmp1_)) {
		g_debug ("scheduler.vala:137: calculate_time_block_completion_time: `start_time`" \
" is not set");
		result = FT_TIMESTAMP_UNDEFINED;
		block38_data_unref (_data38_);
		_data38_ = NULL;
		return result;
	}
	intended_duration = ft_time_block_get_intended_duration (time_block);
	if (intended_duration == ((gint64) 0)) {
		FtState _tmp2_;
		FtState _tmp3_;
		_tmp2_ = ft_time_block_get_state (time_block);
		_tmp3_ = _tmp2_;
		intended_duration = ft_session_template_get_duration (&self->priv->_session_template, _tmp3_);
	}
	_tmp5_ = ft_time_block_get_state (time_block);
	_tmp6_ = _tmp5_;
	if (_tmp6_ == FT_STATE_LONG_BREAK) {
		FtSessionTemplate _tmp7_;
		_tmp7_ = self->priv->_session_template;
		_tmp4_ = (_tmp7_.short_break_duration + intended_duration) / 2;
	} else {
		_tmp4_ = (gint64) floor (intended_duration * FT_SCHEDULER_COMPLETION_THRESHOLD);
	}
	completion_threshold = _tmp4_;
	_data38_->remaining_elapsed = completion_threshold;
	_tmp8_ = ft_schedulable_get_start_time ((FtSchedulable*) time_block);
	_tmp9_ = _tmp8_;
	_data38_->reference_time = _tmp9_;
	ft_time_block_foreach_gap (time_block, ___lambda31__gfunc, _data38_);
	result = _data38_->reference_time + _data38_->remaining_elapsed;
	block38_data_unref (_data38_);
	_data38_ = NULL;
	return result;
}

static gdouble
ft_scheduler_real_calculate_time_block_score (FtScheduler* self,
                                              FtTimeBlock* time_block,
                                              gint64 timestamp)
{
	gdouble _tmp0_ = 0.0;
	g_critical ("Type `%s' does not implement abstract method `ft_scheduler_calculate_time_block_score'", g_type_name (G_TYPE_FROM_INSTANCE (self)));
	return _tmp0_;
}

gdouble
ft_scheduler_calculate_time_block_score (FtScheduler* self,
                                         FtTimeBlock* time_block,
                                         gint64 timestamp)
{
	FtSchedulerClass* _klass_;
	g_return_val_if_fail (self != NULL, -1.0);
	_klass_ = FT_SCHEDULER_GET_CLASS (self);
	if (_klass_->calculate_time_block_score) {
		return _klass_->calculate_time_block_score (self, time_block, timestamp);
	}
	return -1.0;
}

static gdouble
ft_scheduler_real_calculate_time_block_weight (FtScheduler* self,
                                               FtTimeBlock* time_block)
{
	gdouble _tmp0_ = 0.0;
	g_critical ("Type `%s' does not implement abstract method `ft_scheduler_calculate_time_block_weight'", g_type_name (G_TYPE_FROM_INSTANCE (self)));
	return _tmp0_;
}

gdouble
ft_scheduler_calculate_time_block_weight (FtScheduler* self,
                                          FtTimeBlock* time_block)
{
	FtSchedulerClass* _klass_;
	g_return_val_if_fail (self != NULL, -1.0);
	_klass_ = FT_SCHEDULER_GET_CLASS (self);
	if (_klass_->calculate_time_block_weight) {
		return _klass_->calculate_time_block_weight (self, time_block);
	}
	return -1.0;
}

/**
         * Update given state according to given time-block.
         *
         * The context will hold info about current state of the session.
         */
static void
ft_scheduler_real_resolve_context (FtScheduler* self,
                                   FtTimeBlock* time_block,
                                   gboolean is_resuming,
                                   gint64 timestamp,
                                   FtSchedulerContext* context)
{
	g_critical ("Type `%s' does not implement abstract method `ft_scheduler_resolve_context'", g_type_name (G_TYPE_FROM_INSTANCE (self)));
	return;
}

void
ft_scheduler_resolve_context (FtScheduler* self,
                              FtTimeBlock* time_block,
                              gboolean is_resuming,
                              gint64 timestamp,
                              FtSchedulerContext* context)
{
	FtSchedulerClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = FT_SCHEDULER_GET_CLASS (self);
	if (_klass_->resolve_context) {
		_klass_->resolve_context (self, time_block, is_resuming, timestamp, context);
	}
}

/**
         * Resolve next time-block state according to scheduler state.
         */
static FtState
ft_scheduler_real_resolve_state (FtScheduler* self,
                                 FtSchedulerContext* context)
{
	g_critical ("Type `%s' does not implement abstract method `ft_scheduler_resolve_state'", g_type_name (G_TYPE_FROM_INSTANCE (self)));
	return 0;
}

FtState
ft_scheduler_resolve_state (FtScheduler* self,
                            FtSchedulerContext* context)
{
	FtSchedulerClass* _klass_;
	g_return_val_if_fail (self != NULL, 0);
	_klass_ = FT_SCHEDULER_GET_CLASS (self);
	if (_klass_->resolve_state) {
		return _klass_->resolve_state (self, context);
	}
	return 0;
}

/**
         * Resolve next time-block according to scheduler state.
         */
static FtTimeBlock*
ft_scheduler_real_resolve_time_block (FtScheduler* self,
                                      FtSchedulerContext* context)
{
	g_critical ("Type `%s' does not implement abstract method `ft_scheduler_resolve_time_block'", g_type_name (G_TYPE_FROM_INSTANCE (self)));
	return NULL;
}

FtTimeBlock*
ft_scheduler_resolve_time_block (FtScheduler* self,
                                 FtSchedulerContext* context)
{
	FtSchedulerClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = FT_SCHEDULER_GET_CLASS (self);
	if (_klass_->resolve_time_block) {
		return _klass_->resolve_time_block (self, context);
	}
	return NULL;
}

/**
         * Check whether time-block has been completed at given time.
         */
static gboolean
ft_scheduler_real_is_time_block_completed (FtScheduler* self,
                                           FtTimeBlock* time_block,
                                           gint64 timestamp)
{
	gboolean _tmp0_ = FALSE;
	g_critical ("Type `%s' does not implement abstract method `ft_scheduler_is_time_block_completed'", g_type_name (G_TYPE_FROM_INSTANCE (self)));
	return _tmp0_;
}

gboolean
ft_scheduler_is_time_block_completed (FtScheduler* self,
                                      FtTimeBlock* time_block,
                                      gint64 timestamp)
{
	FtSchedulerClass* _klass_;
	g_return_val_if_fail (self != NULL, FALSE);
	_klass_ = FT_SCHEDULER_GET_CLASS (self);
	if (_klass_->is_time_block_completed) {
		return _klass_->is_time_block_completed (self, time_block, timestamp);
	}
	return FALSE;
}

/**
         * Build a scheduler context from completed/in-progress time-blocks.
         */
static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

void
ft_scheduler_build_scheduler_context (FtScheduler* self,
                                      FtSession* session,
                                      gboolean is_resuming,
                                      gint64 timestamp,
                                      FtSchedulerContext* context,
                                      GList** first_scheduled_link)
{
	FtSchedulerContext _vala_context = {0};
	GList* _vala_first_scheduled_link = NULL;
	GList* link = NULL;
	GList* _tmp0_;
	GList* _tmp1_;
	gint64 _tmp2_ = 0LL;
	gboolean _tmp3_ = FALSE;
	GList* _tmp4_;
	FtSchedulerContext _tmp11_ = {0};
	FtSchedulerContext _tmp26_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (session != NULL);
	_tmp0_ = session->time_blocks;
	_tmp1_ = g_list_first (_tmp0_);
	link = _tmp1_;
	_tmp4_ = link;
	if (_tmp4_ != NULL) {
		GList* _tmp5_;
		gconstpointer _tmp6_;
		_tmp5_ = link;
		_tmp6_ = _tmp5_->data;
		_tmp3_ = ft_time_block_get_status ((FtTimeBlock*) _tmp6_) != FT_TIME_BLOCK_STATUS_SCHEDULED;
	} else {
		_tmp3_ = FALSE;
	}
	if (_tmp3_) {
		GList* _tmp7_;
		gconstpointer _tmp8_;
		gint64 _tmp9_;
		gint64 _tmp10_;
		_tmp7_ = link;
		_tmp8_ = _tmp7_->data;
		_tmp9_ = ft_schedulable_get_start_time ((FtSchedulable*) ((FtTimeBlock*) _tmp8_));
		_tmp10_ = _tmp9_;
		_tmp2_ = _tmp10_;
	} else {
		_tmp2_ = timestamp;
	}
	ft_scheduler_context_initial (_tmp2_, &_tmp11_);
	_vala_context = _tmp11_;
	_vala_first_scheduled_link = NULL;
	while (TRUE) {
		GList* _tmp12_;
		FtTimeBlock* time_block = NULL;
		GList* _tmp13_;
		gconstpointer _tmp14_;
		FtTimeBlock* _tmp15_;
		FtTimeBlockStatus time_block_status = 0;
		FtTimeBlock* _tmp16_;
		FtSchedulerContext _tmp18_;
		GList* _tmp24_;
		GList* _tmp25_;
		_tmp12_ = link;
		if (!(_tmp12_ != NULL)) {
			break;
		}
		_tmp13_ = link;
		_tmp14_ = _tmp13_->data;
		_tmp15_ = _g_object_ref0 ((FtTimeBlock*) _tmp14_);
		time_block = _tmp15_;
		_tmp16_ = time_block;
		time_block_status = ft_time_block_get_status (_tmp16_);
		if (time_block_status == FT_TIME_BLOCK_STATUS_SCHEDULED) {
			GList* _tmp17_;
			_tmp17_ = link;
			_vala_first_scheduled_link = _tmp17_;
			_g_object_unref0 (time_block);
			break;
		}
		_tmp18_ = _vala_context;
		if (!_tmp18_.is_session_completed) {
			gint64 _tmp19_ = 0LL;
			gint64 time_block_timestamp = 0LL;
			FtTimeBlock* _tmp23_;
			if (time_block_status == FT_TIME_BLOCK_STATUS_IN_PROGRESS) {
				_tmp19_ = timestamp;
			} else {
				FtTimeBlock* _tmp20_;
				gint64 _tmp21_;
				gint64 _tmp22_;
				_tmp20_ = time_block;
				_tmp21_ = ft_schedulable_get_end_time ((FtSchedulable*) _tmp20_);
				_tmp22_ = _tmp21_;
				_tmp19_ = _tmp22_;
			}
			time_block_timestamp = _tmp19_;
			_tmp23_ = time_block;
			ft_scheduler_resolve_context (self, _tmp23_, is_resuming, time_block_timestamp, &_vala_context);
		}
		_tmp24_ = link;
		_tmp25_ = _tmp24_->next;
		link = _tmp25_;
		_g_object_unref0 (time_block);
	}
	_tmp26_ = _vala_context;
	_vala_context.timestamp = MAX (_tmp26_.timestamp, timestamp);
	if (context) {
		*context = _vala_context;
	}
	if (first_scheduled_link) {
		*first_scheduled_link = _vala_first_scheduled_link;
	}
}

/**
         * Adjust time-block start-time and duration.
         */
void
ft_scheduler_reschedule_time_block (FtScheduler* self,
                                    FtTimeBlock* time_block,
                                    gint64 timestamp)
{
	FtState _tmp0_;
	FtState _tmp1_;
	gboolean _tmp2_ = FALSE;
	g_return_if_fail (self != NULL);
	g_return_if_fail (time_block != NULL);
	_tmp0_ = ft_time_block_get_state (time_block);
	_tmp1_ = _tmp0_;
	if (_tmp1_ == FT_STATE_STOPPED) {
		return;
	}
	if (ft_time_block_get_status (time_block) == FT_TIME_BLOCK_STATUS_COMPLETED) {
		_tmp2_ = TRUE;
	} else {
		_tmp2_ = ft_time_block_get_status (time_block) == FT_TIME_BLOCK_STATUS_UNCOMPLETED;
	}
	if (_tmp2_) {
		return;
	}
	ft_ensure_timestamp (&timestamp);
	if (ft_time_block_get_status (time_block) == FT_TIME_BLOCK_STATUS_SCHEDULED) {
		gint64 intended_duration = 0LL;
		FtState _tmp3_;
		FtState _tmp4_;
		_tmp3_ = ft_time_block_get_state (time_block);
		_tmp4_ = _tmp3_;
		intended_duration = ft_session_template_get_duration (&self->priv->_session_template, _tmp4_);
		ft_time_block_set_intended_duration (time_block, intended_duration);
		ft_schedulable_set_time_range ((FtSchedulable*) time_block, timestamp, timestamp + intended_duration);
	}
	ft_time_block_set_completion_time (time_block, ft_scheduler_calculate_time_block_completion_time (self, time_block));
	ft_time_block_set_weight (time_block, ft_scheduler_calculate_time_block_weight (self, time_block));
}

gboolean
ft_scheduler_reschedule_session (FtScheduler* self,
                                 FtSession* session,
                                 FtTimeBlock* next_time_block,
                                 gboolean is_resuming,
                                 gint64 timestamp)
{
	FtSchedulerContext context = {0};
	GList* link = NULL;
	gulong initial_version = 0UL;
	FtSchedulerContext _tmp0_ = {0};
	GList* _tmp1_ = NULL;
	gint i = 0;
	GList* _tmp53_;
	GList* _tmp54_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (session != NULL, FALSE);
	ft_ensure_timestamp (&timestamp);
	initial_version = session->version;
	ft_session_freeze_changed (session);
	ft_scheduler_ensure_session_meta (self, session);
	ft_scheduler_build_scheduler_context (self, session, is_resuming, timestamp, &_tmp0_, &_tmp1_);
	context = _tmp0_;
	link = _tmp1_;
	if (next_time_block != NULL) {
		gint64 _tmp10_;
		gint64 _tmp11_;
		GList* _tmp12_;
		GList* _tmp13_;
		_vala_assert (ft_session_contains (session, next_time_block), "session.contains (next_time_block)");
		_vala_assert (ft_time_block_get_status (next_time_block) == FT_TIME_BLOCK_STATUS_SCHEDULED, "next_time_block.get_status () == Ft.TimeBlockStatus.SCHEDULED");
		while (TRUE) {
			gboolean _tmp2_ = FALSE;
			GList* _tmp3_;
			GList* tmp = NULL;
			GList* _tmp6_;
			GList* _tmp7_;
			GList* _tmp8_;
			GList* _tmp9_;
			_tmp3_ = link;
			if (_tmp3_ != NULL) {
				GList* _tmp4_;
				gconstpointer _tmp5_;
				_tmp4_ = link;
				_tmp5_ = _tmp4_->data;
				_tmp2_ = ((FtTimeBlock*) _tmp5_) != next_time_block;
			} else {
				_tmp2_ = FALSE;
			}
			if (!_tmp2_) {
				break;
			}
			_tmp6_ = link;
			_tmp7_ = _tmp6_->next;
			tmp = _tmp7_;
			_tmp8_ = link;
			ft_session_remove_link (session, _tmp8_);
			_tmp9_ = tmp;
			link = _tmp9_;
		}
		_tmp10_ = ft_schedulable_get_duration ((FtSchedulable*) next_time_block);
		_tmp11_ = _tmp10_;
		if (_tmp11_ > ((gint64) 0)) {
			ft_schedulable_move_to ((FtSchedulable*) next_time_block, timestamp);
		} else {
			ft_scheduler_reschedule_time_block (self, next_time_block, timestamp);
		}
		ft_scheduler_resolve_context (self, next_time_block, FALSE, timestamp, &context);
		_tmp12_ = link;
		_tmp13_ = _tmp12_->next;
		link = _tmp13_;
	}
	i = 1;
	while (TRUE) {
		gint _tmp14_;
		FtTimeBlock* time_block = NULL;
		FtSchedulerContext _tmp15_;
		FtTimeBlock* _tmp16_;
		FtTimeBlock* _tmp17_;
		gboolean _tmp18_ = FALSE;
		GList* _tmp19_;
		_tmp14_ = i;
		i = _tmp14_ + 1;
		if (((guint) _tmp14_) >= FT_SCHEDULER_MAX_ITERATIONS) {
			g_error ("scheduler.vala:328: `Session.reschedule()` reached iterations limit.");
		}
		_tmp15_ = context;
		_tmp16_ = ft_scheduler_resolve_time_block (self, &_tmp15_);
		time_block = _tmp16_;
		_tmp17_ = time_block;
		if (_tmp17_ == NULL) {
			_g_object_unref0 (time_block);
			break;
		}
		_tmp19_ = link;
		if (_tmp19_ != NULL) {
			GList* _tmp20_;
			gconstpointer _tmp21_;
			FtState _tmp22_;
			FtState _tmp23_;
			FtTimeBlock* _tmp24_;
			FtState _tmp25_;
			FtState _tmp26_;
			_tmp20_ = link;
			_tmp21_ = _tmp20_->data;
			_tmp22_ = ft_time_block_get_state ((FtTimeBlock*) _tmp21_);
			_tmp23_ = _tmp22_;
			_tmp24_ = time_block;
			_tmp25_ = ft_time_block_get_state (_tmp24_);
			_tmp26_ = _tmp25_;
			_tmp18_ = _tmp23_ == _tmp26_;
		} else {
			_tmp18_ = FALSE;
		}
		if (_tmp18_) {
			GList* _tmp27_;
			gconstpointer _tmp28_;
			GList* _tmp29_;
			gconstpointer _tmp30_;
			FtTimeBlock* _tmp31_;
			gint64 _tmp32_;
			gint64 _tmp33_;
			FtTimeBlock* _tmp34_;
			gint64 _tmp35_;
			gint64 _tmp36_;
			GList* _tmp37_;
			gconstpointer _tmp38_;
			FtTimeBlock* _tmp39_;
			FtTimeBlockMeta _tmp40_ = {0};
			GList* _tmp41_;
			gconstpointer _tmp42_;
			GList* _tmp43_;
			GList* _tmp44_;
			_tmp27_ = link;
			_tmp28_ = _tmp27_->data;
			_vala_assert (ft_time_block_get_status ((FtTimeBlock*) _tmp28_) == FT_TIME_BLOCK_STATUS_SCHEDULED, "link.data.get_status () == Ft.TimeBlockStatus.SCHEDULED");
			_tmp29_ = link;
			_tmp30_ = _tmp29_->data;
			_tmp31_ = time_block;
			_tmp32_ = ft_schedulable_get_start_time ((FtSchedulable*) _tmp31_);
			_tmp33_ = _tmp32_;
			_tmp34_ = time_block;
			_tmp35_ = ft_schedulable_get_end_time ((FtSchedulable*) _tmp34_);
			_tmp36_ = _tmp35_;
			ft_schedulable_set_time_range ((FtSchedulable*) ((FtTimeBlock*) _tmp30_), _tmp33_, _tmp36_);
			_tmp37_ = link;
			_tmp38_ = _tmp37_->data;
			_tmp39_ = time_block;
			ft_time_block_get_meta (_tmp39_, &_tmp40_);
			ft_time_block_set_meta ((FtTimeBlock*) _tmp38_, &_tmp40_);
			_tmp41_ = link;
			_tmp42_ = _tmp41_->data;
			ft_scheduler_resolve_context (self, (FtTimeBlock*) _tmp42_, FALSE, timestamp, &context);
			_tmp43_ = link;
			_tmp44_ = _tmp43_->next;
			link = _tmp44_;
		} else {
			GList* _tmp45_;
			FtTimeBlock* _tmp51_;
			FtTimeBlock* _tmp52_;
			_tmp45_ = link;
			if (_tmp45_ != NULL) {
				GList* _tmp46_;
				FtTimeBlock* _tmp47_;
				FtTimeBlock* _tmp48_;
				_tmp46_ = link;
				_tmp47_ = time_block;
				_tmp48_ = _g_object_ref0 (_tmp47_);
				session->time_blocks = g_list_insert_before (session->time_blocks, _tmp46_, _tmp48_);
			} else {
				FtTimeBlock* _tmp49_;
				FtTimeBlock* _tmp50_;
				_tmp49_ = time_block;
				_tmp50_ = _g_object_ref0 (_tmp49_);
				session->time_blocks = g_list_append (session->time_blocks, _tmp50_);
			}
			_tmp51_ = time_block;
			ft_session_emit_added (session, _tmp51_);
			_tmp52_ = time_block;
			ft_scheduler_resolve_context (self, _tmp52_, FALSE, timestamp, &context);
		}
		_g_object_unref0 (time_block);
	}
	_tmp53_ = link;
	ft_session_remove_links_after (session, _tmp53_);
	_tmp54_ = link;
	ft_session_remove_link (session, _tmp54_);
	ft_session_thaw_changed (session);
	result = session->version != initial_version;
	return result;
}

void
ft_scheduler_ensure_time_block_meta (FtScheduler* self,
                                     FtTimeBlock* time_block)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (time_block != NULL);
	if (ft_time_block_get_intended_duration (time_block) == ((gint64) 0)) {
		FtState _tmp0_;
		FtState _tmp1_;
		_tmp0_ = ft_time_block_get_state (time_block);
		_tmp1_ = _tmp0_;
		ft_time_block_set_intended_duration (time_block, ft_session_template_get_duration (&self->priv->_session_template, _tmp1_));
	}
	ft_time_block_set_completion_time (time_block, ft_scheduler_calculate_time_block_completion_time (self, time_block));
	ft_time_block_set_weight (time_block, ft_scheduler_calculate_time_block_weight (self, time_block));
}

/**
         * Update meta for all time-blocks, not only scheduled. Intended for restoring a session.
         */
static void
__lambda32_ (FtScheduler* self,
             FtTimeBlock* time_block)
{
	FtState _tmp0_;
	FtState _tmp1_;
	g_return_if_fail (time_block != NULL);
	_tmp0_ = ft_time_block_get_state (time_block);
	_tmp1_ = _tmp0_;
	if (_tmp1_ != FT_STATE_STOPPED) {
		ft_scheduler_ensure_time_block_meta (self, time_block);
	}
}

static void
___lambda32__gfunc (gconstpointer data,
                    gpointer self)
{
	__lambda32_ ((FtScheduler*) self, (FtTimeBlock*) data);
}

void
ft_scheduler_ensure_session_meta (FtScheduler* self,
                                  FtSession* session)
{
	g_return_if_fail (self != NULL);
	g_return_if_fail (session != NULL);
	ft_session_foreach (session, ___lambda32__gfunc, self);
}

FtScheduler*
ft_scheduler_construct (GType object_type)
{
	FtScheduler * self = NULL;
	self = (FtScheduler*) g_object_new (object_type, NULL);
	return self;
}

void
ft_scheduler_get_session_template (FtScheduler* self,
                                   FtSessionTemplate * result)
{
	FtSessionTemplate _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_session_template;
	*result = _tmp0_;
	return;
}

void
ft_scheduler_set_session_template (FtScheduler* self,
                                   FtSessionTemplate * value)
{
	FtSessionTemplate _tmp0_;
	FtSessionTemplate _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp0_ = *value;
	if (ft_session_template_equals (&self->priv->_session_template, &_tmp0_)) {
		return;
	}
	_tmp1_ = *value;
	self->priv->_session_template = _tmp1_;
	g_object_notify ((GObject*) self, "session-template");
}

static void
ft_scheduler_class_init (FtSchedulerClass * klass,
                         gpointer klass_data)
{
	ft_scheduler_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &FtScheduler_private_offset);
	((FtSchedulerClass *) klass)->calculate_time_block_score = (gdouble (*) (FtScheduler*, FtTimeBlock*, gint64)) ft_scheduler_real_calculate_time_block_score;
	((FtSchedulerClass *) klass)->calculate_time_block_weight = (gdouble (*) (FtScheduler*, FtTimeBlock*)) ft_scheduler_real_calculate_time_block_weight;
	((FtSchedulerClass *) klass)->resolve_context = (void (*) (FtScheduler*, FtTimeBlock*, gboolean, gint64, FtSchedulerContext*)) ft_scheduler_real_resolve_context;
	((FtSchedulerClass *) klass)->resolve_state = (FtState (*) (FtScheduler*, FtSchedulerContext*)) ft_scheduler_real_resolve_state;
	((FtSchedulerClass *) klass)->resolve_time_block = (FtTimeBlock* (*) (FtScheduler*, FtSchedulerContext*)) ft_scheduler_real_resolve_time_block;
	((FtSchedulerClass *) klass)->is_time_block_completed = (gboolean (*) (FtScheduler*, FtTimeBlock*, gint64)) ft_scheduler_real_is_time_block_completed;
	G_OBJECT_CLASS (klass)->get_property = _vala_ft_scheduler_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_ft_scheduler_set_property;
	G_OBJECT_CLASS (klass)->finalize = ft_scheduler_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_SCHEDULER_SESSION_TEMPLATE_PROPERTY, ft_scheduler_properties[FT_SCHEDULER_SESSION_TEMPLATE_PROPERTY] = g_param_spec_boxed ("session-template", "session-template", "session-template", FT_TYPE_SESSION_TEMPLATE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_EXPLICIT_NOTIFY));
}

static void
ft_scheduler_instance_init (FtScheduler * self,
                            gpointer klass)
{
	self->priv = ft_scheduler_get_instance_private (self);
}

static void
ft_scheduler_finalize (GObject * obj)
{
	FtScheduler * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, FT_TYPE_SCHEDULER, FtScheduler);
	G_OBJECT_CLASS (ft_scheduler_parent_class)->finalize (obj);
}

/**
     * Scheduler helps in determining next time-block in a session.
     *
     * It works in a step-wise fashion. It tries to make a best guess according to `SchedulerContext`.
     *
     * In future we would like to align time-blocks to calendar events and working time.
     */
static GType
ft_scheduler_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (FtSchedulerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ft_scheduler_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (FtScheduler), 0, (GInstanceInitFunc) ft_scheduler_instance_init, NULL };
	GType ft_scheduler_type_id;
	ft_scheduler_type_id = g_type_register_static (G_TYPE_OBJECT, "FtScheduler", &g_define_type_info, G_TYPE_FLAG_ABSTRACT);
	FtScheduler_private_offset = g_type_add_instance_private (ft_scheduler_type_id, sizeof (FtSchedulerPrivate));
	return ft_scheduler_type_id;
}

GType
ft_scheduler_get_type (void)
{
	static volatile gsize ft_scheduler_type_id__once = 0;
	if (g_once_init_enter (&ft_scheduler_type_id__once)) {
		GType ft_scheduler_type_id;
		ft_scheduler_type_id = ft_scheduler_get_type_once ();
		g_once_init_leave (&ft_scheduler_type_id__once, ft_scheduler_type_id);
	}
	return ft_scheduler_type_id__once;
}

static void
_vala_ft_scheduler_get_property (GObject * object,
                                 guint property_id,
                                 GValue * value,
                                 GParamSpec * pspec)
{
	FtScheduler * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, FT_TYPE_SCHEDULER, FtScheduler);
	switch (property_id) {
		case FT_SCHEDULER_SESSION_TEMPLATE_PROPERTY:
		{
			FtSessionTemplate boxed;
			ft_scheduler_get_session_template (self, &boxed);
			g_value_set_boxed (value, &boxed);
		}
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_ft_scheduler_set_property (GObject * object,
                                 guint property_id,
                                 const GValue * value,
                                 GParamSpec * pspec)
{
	FtScheduler * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, FT_TYPE_SCHEDULER, FtScheduler);
	switch (property_id) {
		case FT_SCHEDULER_SESSION_TEMPLATE_PROPERTY:
		ft_scheduler_set_session_template (self, g_value_get_boxed (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static inline gpointer
ft_simple_scheduler_get_instance_private (FtSimpleScheduler* self)
{
	return G_STRUCT_MEMBER_P (self, FtSimpleScheduler_private_offset);
}

FtSimpleScheduler*
ft_simple_scheduler_construct_with_template (GType object_type,
                                             FtSessionTemplate* session_template)
{
	FtSimpleScheduler * self = NULL;
	FtSessionTemplate _tmp0_;
	g_return_val_if_fail (session_template != NULL, NULL);
	_tmp0_ = *session_template;
	self = (FtSimpleScheduler*) g_object_new (object_type, "session-template", &_tmp0_, NULL);
	return self;
}

FtSimpleScheduler*
ft_simple_scheduler_new_with_template (FtSessionTemplate* session_template)
{
	return ft_simple_scheduler_construct_with_template (FT_TYPE_SIMPLE_SCHEDULER, session_template);
}

/**
         * Calculate elapsed time at given timestamp, accounting only for completed gaps.
         *
         * Unlike `TimeBlock.calculate_elapsed()`, the timestamp is not clamped to `end_time`
         * and ongoing gaps are ignored. This mirrors how `calculate_time_block_completion_time()`
         * treats gaps, so it can reconstruct the progress at `completion_time` even after
         * the time-block has ended early or while it's paused.
         */
static Block39Data*
block39_data_ref (Block39Data* _data39_)
{
	g_atomic_int_inc (&_data39_->_ref_count_);
	return _data39_;
}

static void
block39_data_unref (void * _userdata_)
{
	Block39Data* _data39_;
	_data39_ = (Block39Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data39_->_ref_count_)) {
		FtSimpleScheduler* self;
		self = _data39_->self;
		_g_object_unref0 (self);
		g_slice_free (Block39Data, _data39_);
	}
}

static void
__lambda58_ (Block39Data* _data39_,
             FtGap* gap)
{
	FtSimpleScheduler* self;
	gint64 _tmp0_;
	gint64 _tmp1_;
	gint64 gap_start_time = 0LL;
	gint64 _tmp2_;
	gint64 _tmp3_;
	gint64 gap_end_time = 0LL;
	gint64 _tmp4_;
	gint64 _tmp5_;
	self = _data39_->self;
	g_return_if_fail (gap != NULL);
	_tmp0_ = ft_schedulable_get_end_time ((FtSchedulable*) gap);
	_tmp1_ = _tmp0_;
	if (ft_timestamp_is_undefined (_tmp1_)) {
		return;
	}
	_tmp2_ = ft_schedulable_get_start_time ((FtSchedulable*) gap);
	_tmp3_ = _tmp2_;
	gap_start_time = CLAMP (_tmp3_, _data39_->range_start, _data39_->timestamp);
	_tmp4_ = ft_schedulable_get_end_time ((FtSchedulable*) gap);
	_tmp5_ = _tmp4_;
	gap_end_time = _tmp5_;
	if (gap_end_time > gap_start_time) {
		gap_end_time = CLAMP (gap_end_time, _data39_->range_start, _data39_->timestamp);
	} else {
		return;
	}
	_data39_->elapsed -= gap_end_time - gap_start_time;
	_data39_->range_start = gap_end_time;
}

static void
___lambda58__gfunc (gconstpointer data,
                    gpointer self)
{
	__lambda58_ (self, (FtGap*) data);
}

static gint64
ft_simple_scheduler_calculate_time_block_elapsed_at (FtSimpleScheduler* self,
                                                     FtTimeBlock* time_block,
                                                     gint64 timestamp)
{
	Block39Data* _data39_;
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gint64 _tmp2_;
	gint64 _tmp3_;
	gint64 _tmp6_;
	gint64 _tmp7_;
	gint64 result;
	g_return_val_if_fail (self != NULL, -1LL);
	g_return_val_if_fail (time_block != NULL, -1LL);
	_data39_ = g_slice_new0 (Block39Data);
	_data39_->_ref_count_ = 1;
	_data39_->self = g_object_ref (self);
	_data39_->timestamp = timestamp;
	_tmp2_ = ft_schedulable_get_start_time ((FtSchedulable*) time_block);
	_tmp3_ = _tmp2_;
	if (ft_timestamp_is_undefined (_tmp3_)) {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = ft_timestamp_is_undefined (_data39_->timestamp);
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		gint64 _tmp4_;
		gint64 _tmp5_;
		_tmp4_ = ft_schedulable_get_start_time ((FtSchedulable*) time_block);
		_tmp5_ = _tmp4_;
		_tmp0_ = _data39_->timestamp <= _tmp5_;
	}
	if (_tmp0_) {
		result = (gint64) 0;
		block39_data_unref (_data39_);
		_data39_ = NULL;
		return result;
	}
	_tmp6_ = ft_schedulable_get_start_time ((FtSchedulable*) time_block);
	_tmp7_ = _tmp6_;
	_data39_->range_start = _tmp7_;
	_data39_->elapsed = _data39_->timestamp - _data39_->range_start;
	ft_time_block_foreach_gap (time_block, ___lambda58__gfunc, _data39_);
	result = _data39_->elapsed;
	block39_data_unref (_data39_);
	_data39_ = NULL;
	return result;
}

static gdouble
ft_simple_scheduler_calculate_time_block_score_internal (FtSimpleScheduler* self,
                                                         FtTimeBlock* time_block,
                                                         gboolean include_uncompleted_gaps,
                                                         gint64 timestamp)
{
	gint64 _tmp0_;
	gint64 _tmp1_;
	gint64 _tmp2_;
	gint64 _tmp3_;
	gint64 _tmp4_;
	gint64 _tmp5_;
	gint64 intended_duration = 0LL;
	gdouble score = 0.0;
	gboolean _tmp10_ = FALSE;
	gboolean _tmp11_ = FALSE;
	FtState _tmp12_;
	FtState _tmp13_;
	gint64 elapsed = 0LL;
	FtGap* last_gap = NULL;
	FtGap* _tmp14_;
	FtGap* _tmp15_;
	gint64 completion_time = 0LL;
	gint64 _tmp16_ = 0LL;
	gint64 completion_threshold = 0LL;
	gboolean _tmp17_ = FALSE;
	gboolean _tmp18_ = FALSE;
	gboolean _tmp19_ = FALSE;
	gboolean _tmp20_ = FALSE;
	gdouble result;
	g_return_val_if_fail (self != NULL, -1.0);
	g_return_val_if_fail (time_block != NULL, -1.0);
	_tmp0_ = ft_schedulable_get_start_time ((FtSchedulable*) time_block);
	_tmp1_ = _tmp0_;
	_vala_return_val_if_fail (ft_timestamp_is_defined (_tmp1_), "Ft.Timestamp.is_defined (time_block.start_time)", -1.0);
	_tmp2_ = ft_schedulable_get_end_time ((FtSchedulable*) time_block);
	_tmp3_ = _tmp2_;
	_tmp4_ = ft_schedulable_get_start_time ((FtSchedulable*) time_block);
	_tmp5_ = _tmp4_;
	_vala_return_val_if_fail (_tmp3_ >= _tmp5_, "time_block.end_time >= time_block.start_time", -1.0);
	intended_duration = ft_time_block_get_intended_duration (time_block);
	score = 0.0;
	if (intended_duration == ((gint64) 0)) {
		FtSessionTemplate _tmp6_ = {0};
		FtSessionTemplate _tmp7_;
		FtState _tmp8_;
		FtState _tmp9_;
		ft_scheduler_get_session_template ((FtScheduler*) self, &_tmp6_);
		_tmp7_ = _tmp6_;
		_tmp8_ = ft_time_block_get_state (time_block);
		_tmp9_ = _tmp8_;
		intended_duration = ft_session_template_get_duration (&_tmp7_, _tmp9_);
	}
	_tmp12_ = ft_time_block_get_state (time_block);
	_tmp13_ = _tmp12_;
	if (_tmp13_ != FT_STATE_POMODORO) {
		_tmp11_ = TRUE;
	} else {
		_tmp11_ = ft_time_block_get_status (time_block) == FT_TIME_BLOCK_STATUS_UNCOMPLETED;
	}
	if (_tmp11_) {
		_tmp10_ = TRUE;
	} else {
		_tmp10_ = intended_duration <= ((gint64) 0);
	}
	if (_tmp10_) {
		result = score;
		return result;
	}
	elapsed = ft_time_block_calculate_elapsed (time_block, timestamp);
	_tmp14_ = ft_time_block_get_last_gap (time_block);
	_tmp15_ = _g_object_ref0 (_tmp14_);
	last_gap = _tmp15_;
	completion_time = ft_time_block_get_completion_time (time_block);
	if (ft_timestamp_is_defined (completion_time)) {
		_tmp16_ = ft_simple_scheduler_calculate_time_block_elapsed_at (self, time_block, completion_time);
	} else {
		_tmp16_ = (gint64) 0;
	}
	completion_threshold = _tmp16_;
	if (completion_threshold <= ((gint64) 0)) {
		completion_threshold = (gint64) floor (intended_duration * FT_SCHEDULER_COMPLETION_THRESHOLD);
	}
	if (include_uncompleted_gaps) {
		FtGap* _tmp21_;
		_tmp21_ = last_gap;
		_tmp20_ = _tmp21_ != NULL;
	} else {
		_tmp20_ = FALSE;
	}
	if (_tmp20_) {
		FtGap* _tmp22_;
		gint64 _tmp23_;
		gint64 _tmp24_;
		_tmp22_ = last_gap;
		_tmp23_ = ft_schedulable_get_start_time ((FtSchedulable*) _tmp22_);
		_tmp24_ = _tmp23_;
		_tmp19_ = _tmp24_ < timestamp;
	} else {
		_tmp19_ = FALSE;
	}
	if (_tmp19_) {
		FtGap* _tmp25_;
		gint64 _tmp26_;
		gint64 _tmp27_;
		_tmp25_ = last_gap;
		_tmp26_ = ft_schedulable_get_end_time ((FtSchedulable*) _tmp25_);
		_tmp27_ = _tmp26_;
		_tmp18_ = ft_timestamp_is_undefined (_tmp27_);
	} else {
		_tmp18_ = FALSE;
	}
	if (_tmp18_) {
		_tmp17_ = ft_time_block_get_status (time_block) == FT_TIME_BLOCK_STATUS_IN_PROGRESS;
	} else {
		_tmp17_ = FALSE;
	}
	if (_tmp17_) {
		gint64 _tmp28_;
		gint64 _tmp29_;
		FtGap* _tmp30_;
		gint64 _tmp31_;
		gint64 _tmp32_;
		_tmp28_ = ft_schedulable_get_end_time ((FtSchedulable*) time_block);
		_tmp29_ = _tmp28_;
		_tmp30_ = last_gap;
		_tmp31_ = ft_schedulable_get_start_time ((FtSchedulable*) _tmp30_);
		_tmp32_ = _tmp31_;
		elapsed += MIN (timestamp, _tmp29_) - _tmp32_;
	}
	if (elapsed >= self->priv->EXTRA_SCORE_THRESHOLD) {
		intended_duration = MAX (intended_duration, self->priv->EXTRA_SCORE_THRESHOLD);
	}
	if (intended_duration >= self->priv->EXTRA_SCORE_THRESHOLD) {
		gint64 base_score = 0LL;
		gdouble partial_score = 0.0;
		base_score = elapsed / intended_duration;
		partial_score = ((gdouble) (elapsed - (base_score * intended_duration))) / ((gdouble) completion_threshold);
		score = CLAMP (floor (((gdouble) base_score) + partial_score), 0.0, self->priv->MAX_SCORE);
	} else {
		score = CLAMP (floor (((gdouble) elapsed) / ((gdouble) completion_threshold)), 0.0, 1.0);
	}
	_vala_assert (isfinite (score), "score.is_finite ()");
	result = score;
	_g_object_unref0 (last_gap);
	return result;
}

static gdouble
ft_simple_scheduler_real_calculate_time_block_score (FtScheduler* base,
                                                     FtTimeBlock* time_block,
                                                     gint64 timestamp)
{
	FtSimpleScheduler * self;
	gdouble result;
	self = (FtSimpleScheduler*) base;
	g_return_val_if_fail (time_block != NULL, -1.0);
	result = ft_simple_scheduler_calculate_time_block_score_internal (self, time_block, FALSE, timestamp);
	return result;
}

static gdouble
ft_simple_scheduler_real_calculate_time_block_weight (FtScheduler* base,
                                                      FtTimeBlock* time_block)
{
	FtSimpleScheduler * self;
	gint64 _tmp0_;
	gint64 _tmp1_;
	gdouble result;
	self = (FtSimpleScheduler*) base;
	g_return_val_if_fail (time_block != NULL, -1.0);
	_tmp0_ = ft_schedulable_get_end_time ((FtSchedulable*) time_block);
	_tmp1_ = _tmp0_;
	result = ft_simple_scheduler_calculate_time_block_score_internal (self, time_block, TRUE, _tmp1_);
	return result;
}

static void
ft_simple_scheduler_real_resolve_context (FtScheduler* base,
                                          FtTimeBlock* time_block,
                                          gboolean is_resuming,
                                          gint64 timestamp,
                                          FtSchedulerContext* context)
{
	FtSimpleScheduler * self;
	FtState _tmp0_;
	FtState _tmp1_;
	FtTimeBlockStatus status = 0;
	gboolean _tmp2_ = FALSE;
	FtState _tmp3_;
	FtState _tmp4_;
	gboolean is_long_break = FALSE;
	gboolean _tmp18_ = FALSE;
	FtState _tmp19_;
	FtState _tmp20_;
	gboolean _tmp21_ = FALSE;
	FtSchedulerContext _tmp22_;
	self = (FtSimpleScheduler*) base;
	g_return_if_fail (time_block != NULL);
	g_return_if_fail (context != NULL);
	_tmp0_ = ft_time_block_get_state (time_block);
	_tmp1_ = _tmp0_;
	if (_tmp1_ == FT_STATE_STOPPED) {
		return;
	}
	status = ft_time_block_get_status (time_block);
	_tmp3_ = ft_time_block_get_state (time_block);
	_tmp4_ = _tmp3_;
	if (_tmp4_ == FT_STATE_LONG_BREAK) {
		_tmp2_ = TRUE;
	} else {
		FtState _tmp5_;
		FtState _tmp6_;
		_tmp5_ = ft_time_block_get_state (time_block);
		_tmp6_ = _tmp5_;
		_tmp2_ = _tmp6_ == FT_STATE_BREAK;
	}
	is_long_break = _tmp2_;
	if (status == FT_TIME_BLOCK_STATUS_IN_PROGRESS) {
		FtGap* last_gap = NULL;
		FtGap* _tmp7_;
		FtGap* _tmp8_;
		gboolean _tmp9_ = FALSE;
		FtGap* _tmp10_;
		gboolean is_paused = FALSE;
		gboolean _tmp14_ = FALSE;
		_tmp7_ = ft_time_block_get_last_gap (time_block);
		_tmp8_ = _g_object_ref0 (_tmp7_);
		last_gap = _tmp8_;
		_tmp10_ = last_gap;
		if (_tmp10_ != NULL) {
			FtGap* _tmp11_;
			gint64 _tmp12_;
			gint64 _tmp13_;
			_tmp11_ = last_gap;
			_tmp12_ = ft_schedulable_get_end_time ((FtSchedulable*) _tmp11_);
			_tmp13_ = _tmp12_;
			_tmp9_ = ft_timestamp_is_undefined (_tmp13_);
		} else {
			_tmp9_ = FALSE;
		}
		is_paused = _tmp9_;
		if (!is_resuming) {
			_tmp14_ = is_paused;
		} else {
			_tmp14_ = FALSE;
		}
		if (_tmp14_) {
			status = FT_TIME_BLOCK_STATUS_COMPLETED;
		} else {
			FtTimeBlockStatus _tmp15_ = 0;
			if (ft_scheduler_is_time_block_completed ((FtScheduler*) self, time_block, timestamp)) {
				_tmp15_ = FT_TIME_BLOCK_STATUS_COMPLETED;
			} else {
				_tmp15_ = FT_TIME_BLOCK_STATUS_UNCOMPLETED;
			}
			status = _tmp15_;
		}
		(*context).timestamp = timestamp;
		_g_object_unref0 (last_gap);
	} else {
		gint64 _tmp16_;
		gint64 _tmp17_;
		_tmp16_ = ft_schedulable_get_end_time ((FtSchedulable*) time_block);
		_tmp17_ = _tmp16_;
		(*context).timestamp = _tmp17_;
	}
	if (status == FT_TIME_BLOCK_STATUS_SCHEDULED) {
		_tmp18_ = TRUE;
	} else {
		_tmp18_ = status == FT_TIME_BLOCK_STATUS_COMPLETED;
	}
	if (_tmp18_) {
		(*context).score = (*context).score + ft_scheduler_calculate_time_block_weight ((FtScheduler*) self, time_block);
		if (is_long_break) {
			(*context).is_session_completed = TRUE;
		}
	}
	_tmp19_ = ft_time_block_get_state (time_block);
	_tmp20_ = _tmp19_;
	(*context).state = _tmp20_;
	_tmp22_ = *context;
	if (!_tmp22_.is_session_completed) {
		FtSchedulerContext _tmp23_;
		FtSessionTemplate _tmp24_ = {0};
		FtSessionTemplate _tmp25_;
		_tmp23_ = *context;
		ft_scheduler_get_session_template ((FtScheduler*) self, &_tmp24_);
		_tmp25_ = _tmp24_;
		_tmp21_ = _tmp23_.score >= ((gdouble) _tmp25_.cycles);
	} else {
		_tmp21_ = FALSE;
	}
	(*context).needs_long_break = _tmp21_;
}

static FtState
ft_simple_scheduler_real_resolve_state (FtScheduler* base,
                                        FtSchedulerContext* context)
{
	FtSimpleScheduler * self;
	FtSchedulerContext _tmp0_;
	FtSessionTemplate _tmp1_ = {0};
	FtSessionTemplate _tmp2_;
	FtState _tmp3_ = 0;
	FtSchedulerContext _tmp4_;
	FtState result;
	self = (FtSimpleScheduler*) base;
	g_return_val_if_fail (context != NULL, 0);
	_tmp0_ = *context;
	if (_tmp0_.state != FT_STATE_POMODORO) {
		result = FT_STATE_POMODORO;
		return result;
	}
	ft_scheduler_get_session_template ((FtScheduler*) self, &_tmp1_);
	_tmp2_ = _tmp1_;
	if (ft_session_template_has_uniform_breaks (&_tmp2_)) {
		result = FT_STATE_BREAK;
		return result;
	}
	_tmp4_ = *context;
	if (_tmp4_.needs_long_break) {
		_tmp3_ = FT_STATE_LONG_BREAK;
	} else {
		_tmp3_ = FT_STATE_SHORT_BREAK;
	}
	result = _tmp3_;
	return result;
}

/**
         * Create next time-block.
         *
         * Alternate between a pomodoro and a break, regardless whether previous time-block has been completed.
         */
static FtTimeBlock*
ft_simple_scheduler_real_resolve_time_block (FtScheduler* base,
                                             FtSchedulerContext* context)
{
	FtSimpleScheduler * self;
	FtSchedulerContext _tmp0_;
	FtState state = 0;
	FtSchedulerContext _tmp1_;
	FtTimeBlock* time_block = NULL;
	FtTimeBlock* _tmp2_;
	FtTimeBlock* _tmp3_;
	FtSchedulerContext _tmp4_;
	FtTimeBlock* result;
	self = (FtSimpleScheduler*) base;
	g_return_val_if_fail (context != NULL, NULL);
	_tmp0_ = *context;
	if (_tmp0_.is_session_completed) {
		result = NULL;
		return result;
	}
	_tmp1_ = *context;
	state = ft_scheduler_resolve_state ((FtScheduler*) self, &_tmp1_);
	_tmp2_ = ft_time_block_new (state);
	g_object_ref_sink (_tmp2_);
	time_block = _tmp2_;
	_tmp3_ = time_block;
	_tmp4_ = *context;
	ft_scheduler_reschedule_time_block ((FtScheduler*) self, _tmp3_, _tmp4_.timestamp);
	result = time_block;
	return result;
}

/**
         * Determine whether time-block should be marked as completed.
         */
static gboolean
ft_simple_scheduler_real_is_time_block_completed (FtScheduler* base,
                                                  FtTimeBlock* time_block,
                                                  gint64 timestamp)
{
	FtSimpleScheduler * self;
	gint64 completion_time = 0LL;
	gboolean result;
	self = (FtSimpleScheduler*) base;
	g_return_val_if_fail (time_block != NULL, FALSE);
	completion_time = ft_time_block_get_completion_time (time_block);
	if (ft_timestamp_is_undefined (completion_time)) {
		completion_time = ft_scheduler_calculate_time_block_completion_time ((FtScheduler*) self, time_block);
	}
	result = timestamp >= completion_time;
	return result;
}

FtSimpleScheduler*
ft_simple_scheduler_construct (GType object_type)
{
	FtSimpleScheduler * self = NULL;
	self = (FtSimpleScheduler*) ft_scheduler_construct (object_type);
	return self;
}

FtSimpleScheduler*
ft_simple_scheduler_new (void)
{
	return ft_simple_scheduler_construct (FT_TYPE_SIMPLE_SCHEDULER);
}

static void
ft_simple_scheduler_class_init (FtSimpleSchedulerClass * klass,
                                gpointer klass_data)
{
	ft_simple_scheduler_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &FtSimpleScheduler_private_offset);
	((FtSchedulerClass *) klass)->calculate_time_block_score = (gdouble (*) (FtScheduler*, FtTimeBlock*, gint64)) ft_simple_scheduler_real_calculate_time_block_score;
	((FtSchedulerClass *) klass)->calculate_time_block_weight = (gdouble (*) (FtScheduler*, FtTimeBlock*)) ft_simple_scheduler_real_calculate_time_block_weight;
	((FtSchedulerClass *) klass)->resolve_context = (void (*) (FtScheduler*, FtTimeBlock*, gboolean, gint64, FtSchedulerContext*)) ft_simple_scheduler_real_resolve_context;
	((FtSchedulerClass *) klass)->resolve_state = (FtState (*) (FtScheduler*, FtSchedulerContext*)) ft_simple_scheduler_real_resolve_state;
	((FtSchedulerClass *) klass)->resolve_time_block = (FtTimeBlock* (*) (FtScheduler*, FtSchedulerContext*)) ft_simple_scheduler_real_resolve_time_block;
	((FtSchedulerClass *) klass)->is_time_block_completed = (gboolean (*) (FtScheduler*, FtTimeBlock*, gint64)) ft_simple_scheduler_real_is_time_block_completed;
	G_OBJECT_CLASS (klass)->finalize = ft_simple_scheduler_finalize;
}

static void
ft_simple_scheduler_instance_init (FtSimpleScheduler * self,
                                   gpointer klass)
{
	self->priv = ft_simple_scheduler_get_instance_private (self);
	self->priv->MAX_SCORE = 2.0;
	self->priv->EXTRA_SCORE_THRESHOLD = 20 * FT_INTERVAL_MINUTE;
}

static void
ft_simple_scheduler_finalize (GObject * obj)
{
	FtSimpleScheduler * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, FT_TYPE_SIMPLE_SCHEDULER, FtSimpleScheduler);
	G_OBJECT_CLASS (ft_simple_scheduler_parent_class)->finalize (obj);
}

static GType
ft_simple_scheduler_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (FtSimpleSchedulerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ft_simple_scheduler_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (FtSimpleScheduler), 0, (GInstanceInitFunc) ft_simple_scheduler_instance_init, NULL };
	GType ft_simple_scheduler_type_id;
	ft_simple_scheduler_type_id = g_type_register_static (FT_TYPE_SCHEDULER, "FtSimpleScheduler", &g_define_type_info, 0);
	FtSimpleScheduler_private_offset = g_type_add_instance_private (ft_simple_scheduler_type_id, sizeof (FtSimpleSchedulerPrivate));
	return ft_simple_scheduler_type_id;
}

GType
ft_simple_scheduler_get_type (void)
{
	static volatile gsize ft_simple_scheduler_type_id__once = 0;
	if (g_once_init_enter (&ft_simple_scheduler_type_id__once)) {
		GType ft_simple_scheduler_type_id;
		ft_simple_scheduler_type_id = ft_simple_scheduler_get_type_once ();
		g_once_init_leave (&ft_simple_scheduler_type_id__once, ft_simple_scheduler_type_id);
	}
	return ft_simple_scheduler_type_id__once;
}

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

