/* potential-match.c generated by valac 0.12.0, the Vala compiler
 * generated from potential-match.vala, do not modify */

/*
 * Copyright (C) 2011 Collabora Ltd.
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *       Raul Gutierrez Segales <raul.gutierrez.segales@collabora.co.uk>
 */

#include <glib.h>
#include <glib-object.h>
#include <gee.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#include <math.h>


#define FOLKS_TYPE_MATCH_RESULT (folks_match_result_get_type ())

#define FOLKS_TYPE_POTENTIAL_MATCH (folks_potential_match_get_type ())
#define FOLKS_POTENTIAL_MATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOLKS_TYPE_POTENTIAL_MATCH, FolksPotentialMatch))
#define FOLKS_POTENTIAL_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FOLKS_TYPE_POTENTIAL_MATCH, FolksPotentialMatchClass))
#define FOLKS_IS_POTENTIAL_MATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOLKS_TYPE_POTENTIAL_MATCH))
#define FOLKS_IS_POTENTIAL_MATCH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FOLKS_TYPE_POTENTIAL_MATCH))
#define FOLKS_POTENTIAL_MATCH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FOLKS_TYPE_POTENTIAL_MATCH, FolksPotentialMatchClass))

typedef struct _FolksPotentialMatch FolksPotentialMatch;
typedef struct _FolksPotentialMatchClass FolksPotentialMatchClass;
typedef struct _FolksPotentialMatchPrivate FolksPotentialMatchPrivate;

#define FOLKS_TYPE_INDIVIDUAL (folks_individual_get_type ())
#define FOLKS_INDIVIDUAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOLKS_TYPE_INDIVIDUAL, FolksIndividual))
#define FOLKS_INDIVIDUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FOLKS_TYPE_INDIVIDUAL, FolksIndividualClass))
#define FOLKS_IS_INDIVIDUAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOLKS_TYPE_INDIVIDUAL))
#define FOLKS_IS_INDIVIDUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FOLKS_TYPE_INDIVIDUAL))
#define FOLKS_INDIVIDUAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FOLKS_TYPE_INDIVIDUAL, FolksIndividualClass))

typedef struct _FolksIndividual FolksIndividual;
typedef struct _FolksIndividualClass FolksIndividualClass;
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))

#define FOLKS_TYPE_GENDER_DETAILS (folks_gender_details_get_type ())
#define FOLKS_GENDER_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOLKS_TYPE_GENDER_DETAILS, FolksGenderDetails))
#define FOLKS_IS_GENDER_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOLKS_TYPE_GENDER_DETAILS))
#define FOLKS_GENDER_DETAILS_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), FOLKS_TYPE_GENDER_DETAILS, FolksGenderDetailsIface))

typedef struct _FolksGenderDetails FolksGenderDetails;
typedef struct _FolksGenderDetailsIface FolksGenderDetailsIface;

#define FOLKS_TYPE_GENDER (folks_gender_get_type ())

#define FOLKS_TYPE_PHONE_DETAILS (folks_phone_details_get_type ())
#define FOLKS_PHONE_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOLKS_TYPE_PHONE_DETAILS, FolksPhoneDetails))
#define FOLKS_IS_PHONE_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOLKS_TYPE_PHONE_DETAILS))
#define FOLKS_PHONE_DETAILS_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), FOLKS_TYPE_PHONE_DETAILS, FolksPhoneDetailsIface))

typedef struct _FolksPhoneDetails FolksPhoneDetails;
typedef struct _FolksPhoneDetailsIface FolksPhoneDetailsIface;

#define FOLKS_TYPE_FIELD_DETAILS (folks_field_details_get_type ())
#define FOLKS_FIELD_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOLKS_TYPE_FIELD_DETAILS, FolksFieldDetails))
#define FOLKS_FIELD_DETAILS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FOLKS_TYPE_FIELD_DETAILS, FolksFieldDetailsClass))
#define FOLKS_IS_FIELD_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOLKS_TYPE_FIELD_DETAILS))
#define FOLKS_IS_FIELD_DETAILS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FOLKS_TYPE_FIELD_DETAILS))
#define FOLKS_FIELD_DETAILS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FOLKS_TYPE_FIELD_DETAILS, FolksFieldDetailsClass))

typedef struct _FolksFieldDetails FolksFieldDetails;
typedef struct _FolksFieldDetailsClass FolksFieldDetailsClass;
#define _g_free0(var) (var = (g_free (var), NULL))

#define FOLKS_TYPE_NAME_DETAILS (folks_name_details_get_type ())
#define FOLKS_NAME_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOLKS_TYPE_NAME_DETAILS, FolksNameDetails))
#define FOLKS_IS_NAME_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOLKS_TYPE_NAME_DETAILS))
#define FOLKS_NAME_DETAILS_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), FOLKS_TYPE_NAME_DETAILS, FolksNameDetailsIface))

typedef struct _FolksNameDetails FolksNameDetails;
typedef struct _FolksNameDetailsIface FolksNameDetailsIface;

#define FOLKS_TYPE_STRUCTURED_NAME (folks_structured_name_get_type ())
#define FOLKS_STRUCTURED_NAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOLKS_TYPE_STRUCTURED_NAME, FolksStructuredName))
#define FOLKS_STRUCTURED_NAME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FOLKS_TYPE_STRUCTURED_NAME, FolksStructuredNameClass))
#define FOLKS_IS_STRUCTURED_NAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOLKS_TYPE_STRUCTURED_NAME))
#define FOLKS_IS_STRUCTURED_NAME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FOLKS_TYPE_STRUCTURED_NAME))
#define FOLKS_STRUCTURED_NAME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FOLKS_TYPE_STRUCTURED_NAME, FolksStructuredNameClass))

typedef struct _FolksStructuredName FolksStructuredName;
typedef struct _FolksStructuredNameClass FolksStructuredNameClass;

#define FOLKS_TYPE_IM_DETAILS (folks_im_details_get_type ())
#define FOLKS_IM_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOLKS_TYPE_IM_DETAILS, FolksImDetails))
#define FOLKS_IS_IM_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOLKS_TYPE_IM_DETAILS))
#define FOLKS_IM_DETAILS_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), FOLKS_TYPE_IM_DETAILS, FolksImDetailsIface))

typedef struct _FolksImDetails FolksImDetails;
typedef struct _FolksImDetailsIface FolksImDetailsIface;

#define FOLKS_TYPE_EMAIL_DETAILS (folks_email_details_get_type ())
#define FOLKS_EMAIL_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOLKS_TYPE_EMAIL_DETAILS, FolksEmailDetails))
#define FOLKS_IS_EMAIL_DETAILS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOLKS_TYPE_EMAIL_DETAILS))
#define FOLKS_EMAIL_DETAILS_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), FOLKS_TYPE_EMAIL_DETAILS, FolksEmailDetailsIface))

typedef struct _FolksEmailDetails FolksEmailDetails;
typedef struct _FolksEmailDetailsIface FolksEmailDetailsIface;

typedef enum  {
	FOLKS_MATCH_RESULT_VERY_LOW,
	FOLKS_MATCH_RESULT_LOW,
	FOLKS_MATCH_RESULT_MEDIUM,
	FOLKS_MATCH_RESULT_HIGH,
	FOLKS_MATCH_RESULT_VERY_HIGH,
	FOLKS_MATCH_RESULT_MIN = FOLKS_MATCH_RESULT_VERY_LOW,
	FOLKS_MATCH_RESULT_MAX = FOLKS_MATCH_RESULT_VERY_HIGH
} FolksMatchResult;

struct _FolksPotentialMatch {
	GObject parent_instance;
	FolksPotentialMatchPrivate * priv;
};

struct _FolksPotentialMatchClass {
	GObjectClass parent_class;
};

struct _FolksPotentialMatchPrivate {
	FolksMatchResult _result;
	FolksIndividual* _individual_a;
	FolksIndividual* _individual_b;
};

typedef enum  {
	FOLKS_GENDER_UNSPECIFIED,
	FOLKS_GENDER_MALE,
	FOLKS_GENDER_FEMALE
} FolksGender;

struct _FolksGenderDetailsIface {
	GTypeInterface parent_iface;
	FolksGender (*get_gender) (FolksGenderDetails* self);
	void (*set_gender) (FolksGenderDetails* self, FolksGender value);
};

struct _FolksPhoneDetailsIface {
	GTypeInterface parent_iface;
	GeeSet* (*get_phone_numbers) (FolksPhoneDetails* self);
	void (*set_phone_numbers) (FolksPhoneDetails* self, GeeSet* value);
};

struct _FolksNameDetailsIface {
	GTypeInterface parent_iface;
	FolksStructuredName* (*get_structured_name) (FolksNameDetails* self);
	void (*set_structured_name) (FolksNameDetails* self, FolksStructuredName* value);
	const gchar* (*get_full_name) (FolksNameDetails* self);
	void (*set_full_name) (FolksNameDetails* self, const gchar* value);
	const gchar* (*get_nickname) (FolksNameDetails* self);
};

struct _FolksImDetailsIface {
	GTypeInterface parent_iface;
	GeeMultiMap* (*get_im_addresses) (FolksImDetails* self);
	void (*set_im_addresses) (FolksImDetails* self, GeeMultiMap* value);
};

struct _FolksEmailDetailsIface {
	GTypeInterface parent_iface;
	GeeSet* (*get_email_addresses) (FolksEmailDetails* self);
	void (*set_email_addresses) (FolksEmailDetails* self, GeeSet* value);
};


static gpointer folks_potential_match_parent_class = NULL;
extern GeeSet* folks_potential_match_known_email_aliases;
GeeSet* folks_potential_match_known_email_aliases = NULL;
static gdouble folks_potential_match__DIST_THRESHOLD;
static gdouble folks_potential_match__DIST_THRESHOLD = 0.70;

GType folks_match_result_get_type (void) G_GNUC_CONST;
GType folks_potential_match_get_type (void) G_GNUC_CONST;
GType folks_individual_get_type (void) G_GNUC_CONST;
#define FOLKS_POTENTIAL_MATCH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FOLKS_TYPE_POTENTIAL_MATCH, FolksPotentialMatchPrivate))
enum  {
	FOLKS_POTENTIAL_MATCH_DUMMY_PROPERTY
};
#define FOLKS_POTENTIAL_MATCH__SEPARATORS "._-+"
FolksPotentialMatch* folks_potential_match_new (void);
FolksPotentialMatch* folks_potential_match_construct (GType object_type);
FolksMatchResult folks_potential_match_potential_match (FolksPotentialMatch* self, FolksIndividual* a, FolksIndividual* b);
GType folks_gender_get_type (void) G_GNUC_CONST;
GType folks_gender_details_get_type (void) G_GNUC_CONST;
FolksGender folks_gender_details_get_gender (FolksGenderDetails* self);
void _folks_potential_match_inspect_im_addresses (FolksPotentialMatch* self);
static void _folks_potential_match_inspect_emails (FolksPotentialMatch* self);
static void _folks_potential_match_inspect_phone_numbers (FolksPotentialMatch* self);
static void _folks_potential_match_name_similarity (FolksPotentialMatch* self);
GType folks_field_details_get_type (void) G_GNUC_CONST;
GType folks_phone_details_get_type (void) G_GNUC_CONST;
GeeSet* folks_phone_details_get_phone_numbers (FolksPhoneDetails* self);
gboolean folks_phone_details_numbers_equal (const gchar* number1, const gchar* number2);
const gchar* folks_field_details_get_value (FolksFieldDetails* self);
gchar* folks_potential_match_result_to_string (FolksMatchResult _result_);
GType folks_structured_name_get_type (void) G_GNUC_CONST;
GType folks_name_details_get_type (void) G_GNUC_CONST;
FolksStructuredName* folks_name_details_get_structured_name (FolksNameDetails* self);
static gboolean _folks_potential_match_look_alike (FolksPotentialMatch* self, const gchar* a, const gchar* b);
const gchar* folks_name_details_get_nickname (FolksNameDetails* self);
const gchar* folks_name_details_get_full_name (FolksNameDetails* self);
gboolean folks_structured_name_is_empty (FolksStructuredName* self);
gboolean folks_structured_name_equal (FolksStructuredName* self, FolksStructuredName* other);
gboolean _folks_utils_str_equal_safe (const gchar* a, const gchar* b);
const gchar* folks_structured_name_get_given_name (FolksStructuredName* self);
const gchar* folks_structured_name_get_family_name (FolksStructuredName* self);
const gchar* folks_structured_name_get_additional_names (FolksStructuredName* self);
const gchar* folks_structured_name_get_prefixes (FolksStructuredName* self);
const gchar* folks_structured_name_get_suffixes (FolksStructuredName* self);
static FolksMatchResult _folks_potential_match_inc_match_level (FolksPotentialMatch* self, FolksMatchResult current_level, gint times);
GType folks_im_details_get_type (void) G_GNUC_CONST;
GeeMultiMap* folks_im_details_get_im_addresses (FolksImDetails* self);
GType folks_email_details_get_type (void) G_GNUC_CONST;
GeeSet* folks_email_details_get_email_addresses (FolksEmailDetails* self);
static gboolean _folks_potential_match_check_initials_expansion (FolksPotentialMatch* self, gchar** tokens_a, int tokens_a_length1, gchar** tokens_b, int tokens_b_length1);
static gboolean _folks_potential_match_match_tokens (FolksPotentialMatch* self, gchar** tokens_a, int tokens_a_length1, gchar** tokens_b, int tokens_b_length1);
static gboolean _folks_potential_match_do_check_initials_expansion (FolksPotentialMatch* self, gchar** expanded_name, int expanded_name_length1, const gchar* initials);
static gboolean _folks_potential_match_do_match_tokens (FolksPotentialMatch* self, gchar** bigger_set, int bigger_set_length1, gchar** smaller_set, int smaller_set_length1);
gdouble folks_potential_match_jaro_dist (FolksPotentialMatch* self, const gchar* s1, const gchar* s2);
static gint _folks_potential_match_matches (FolksPotentialMatch* self, const gchar* s1, const gchar* s2, gint max_dist, gdouble* t);
static gint _folks_potential_match_contains (FolksPotentialMatch* self, const gchar* haystack, const gchar* c, gint pos, gint max_dist);
static void folks_potential_match_finalize (GObject* obj);
static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func);
static gint _vala_array_length (gpointer array);


/**
 * Likely-ness of a potential match.
 *
 * Note that the order should be maintained.
 */
GType folks_match_result_get_type (void) {
	static volatile gsize folks_match_result_type_id__volatile = 0;
	if (g_once_init_enter (&folks_match_result_type_id__volatile)) {
		static const GEnumValue values[] = {{FOLKS_MATCH_RESULT_VERY_LOW, "FOLKS_MATCH_RESULT_VERY_LOW", "very-low"}, {FOLKS_MATCH_RESULT_LOW, "FOLKS_MATCH_RESULT_LOW", "low"}, {FOLKS_MATCH_RESULT_MEDIUM, "FOLKS_MATCH_RESULT_MEDIUM", "medium"}, {FOLKS_MATCH_RESULT_HIGH, "FOLKS_MATCH_RESULT_HIGH", "high"}, {FOLKS_MATCH_RESULT_VERY_HIGH, "FOLKS_MATCH_RESULT_VERY_HIGH", "very-high"}, {FOLKS_MATCH_RESULT_MIN, "FOLKS_MATCH_RESULT_MIN", "min"}, {FOLKS_MATCH_RESULT_MAX, "FOLKS_MATCH_RESULT_MAX", "max"}, {0, NULL, NULL}};
		GType folks_match_result_type_id;
		folks_match_result_type_id = g_enum_register_static ("FolksMatchResult", values);
		g_once_init_leave (&folks_match_result_type_id__volatile, folks_match_result_type_id);
	}
	return folks_match_result_type_id__volatile;
}


FolksPotentialMatch* folks_potential_match_construct (GType object_type) {
	FolksPotentialMatch * self = NULL;
	self = (FolksPotentialMatch*) g_object_new (object_type, NULL);
	if (folks_potential_match_known_email_aliases == NULL) {
		GeeHashSet* _tmp0_ = NULL;
		_tmp0_ = gee_hash_set_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, g_free, g_str_hash, g_str_equal);
		_g_object_unref0 (folks_potential_match_known_email_aliases);
		folks_potential_match_known_email_aliases = (GeeSet*) _tmp0_;
		gee_collection_add ((GeeCollection*) folks_potential_match_known_email_aliases, "admin");
		gee_collection_add ((GeeCollection*) folks_potential_match_known_email_aliases, "abuse");
		gee_collection_add ((GeeCollection*) folks_potential_match_known_email_aliases, "webmaster");
	}
	return self;
}


FolksPotentialMatch* folks_potential_match_new (void) {
	return folks_potential_match_construct (FOLKS_TYPE_POTENTIAL_MATCH);
}


/**
   * Whether two individuals are likely to be the same person.
   *
   * @since 0.5.0
   */
static gpointer _g_object_ref0 (gpointer self) {
	return self ? g_object_ref (self) : NULL;
}


FolksMatchResult folks_potential_match_potential_match (FolksPotentialMatch* self, FolksIndividual* a, FolksIndividual* b) {
	FolksMatchResult result = 0;
	FolksIndividual* _tmp0_;
	FolksIndividual* _tmp1_;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_ = FALSE;
	FolksGender _tmp4_;
	g_return_val_if_fail (self != NULL, 0);
	g_return_val_if_fail (a != NULL, 0);
	g_return_val_if_fail (b != NULL, 0);
	_tmp0_ = _g_object_ref0 (a);
	_g_object_unref0 (self->priv->_individual_a);
	self->priv->_individual_a = _tmp0_;
	_tmp1_ = _g_object_ref0 (b);
	_g_object_unref0 (self->priv->_individual_b);
	self->priv->_individual_b = _tmp1_;
	self->priv->_result = FOLKS_MATCH_RESULT_MIN;
	_tmp4_ = folks_gender_details_get_gender ((FolksGenderDetails*) self->priv->_individual_a);
	if (_tmp4_ != FOLKS_GENDER_UNSPECIFIED) {
		FolksGender _tmp5_;
		_tmp5_ = folks_gender_details_get_gender ((FolksGenderDetails*) self->priv->_individual_b);
		_tmp3_ = _tmp5_ != FOLKS_GENDER_UNSPECIFIED;
	} else {
		_tmp3_ = FALSE;
	}
	if (_tmp3_) {
		FolksGender _tmp6_;
		FolksGender _tmp7_;
		_tmp6_ = folks_gender_details_get_gender ((FolksGenderDetails*) self->priv->_individual_a);
		_tmp7_ = folks_gender_details_get_gender ((FolksGenderDetails*) self->priv->_individual_b);
		_tmp2_ = _tmp6_ != _tmp7_;
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		result = self->priv->_result;
		return result;
	}
	_folks_potential_match_inspect_im_addresses (self);
	if (self->priv->_result == FOLKS_MATCH_RESULT_MAX) {
		result = self->priv->_result;
		return result;
	}
	_folks_potential_match_inspect_emails (self);
	if (self->priv->_result == FOLKS_MATCH_RESULT_MAX) {
		result = self->priv->_result;
		return result;
	}
	_folks_potential_match_inspect_phone_numbers (self);
	if (self->priv->_result == FOLKS_MATCH_RESULT_MAX) {
		result = self->priv->_result;
		return result;
	}
	_folks_potential_match_name_similarity (self);
	if (self->priv->_result == FOLKS_MATCH_RESULT_MAX) {
		result = self->priv->_result;
		return result;
	}
	result = self->priv->_result;
	return result;
}


static void _folks_potential_match_inspect_phone_numbers (FolksPotentialMatch* self) {
	GeeSet* _tmp0_ = NULL;
	GeeSet* _tmp1_;
	GeeSet* set_a;
	GeeSet* _tmp2_ = NULL;
	GeeSet* _tmp3_;
	GeeSet* set_b;
	g_return_if_fail (self != NULL);
	_tmp0_ = folks_phone_details_get_phone_numbers ((FolksPhoneDetails*) self->priv->_individual_a);
	_tmp1_ = _g_object_ref0 (_tmp0_);
	set_a = _tmp1_;
	_tmp2_ = folks_phone_details_get_phone_numbers ((FolksPhoneDetails*) self->priv->_individual_b);
	_tmp3_ = _g_object_ref0 (_tmp2_);
	set_b = _tmp3_;
	{
		GeeIterator* _tmp4_ = NULL;
		GeeIterator* _fd_a_it;
		_tmp4_ = gee_iterable_iterator ((GeeIterable*) set_a);
		_fd_a_it = _tmp4_;
		while (TRUE) {
			gboolean _tmp5_;
			gpointer _tmp6_ = NULL;
			FolksFieldDetails* fd_a;
			_tmp5_ = gee_iterator_next (_fd_a_it);
			if (!_tmp5_) {
				break;
			}
			_tmp6_ = gee_iterator_get (_fd_a_it);
			fd_a = (FolksFieldDetails*) _tmp6_;
			{
				GeeIterator* _tmp7_ = NULL;
				GeeIterator* _fd_b_it;
				_tmp7_ = gee_iterable_iterator ((GeeIterable*) set_b);
				_fd_b_it = _tmp7_;
				while (TRUE) {
					gboolean _tmp8_;
					gpointer _tmp9_ = NULL;
					FolksFieldDetails* fd_b;
					const gchar* _tmp10_ = NULL;
					const gchar* _tmp11_ = NULL;
					gboolean _tmp12_;
					_tmp8_ = gee_iterator_next (_fd_b_it);
					if (!_tmp8_) {
						break;
					}
					_tmp9_ = gee_iterator_get (_fd_b_it);
					fd_b = (FolksFieldDetails*) _tmp9_;
					_tmp10_ = folks_field_details_get_value (fd_a);
					_tmp11_ = folks_field_details_get_value (fd_b);
					_tmp12_ = folks_phone_details_numbers_equal (_tmp10_, _tmp11_);
					if (_tmp12_) {
						self->priv->_result = FOLKS_MATCH_RESULT_HIGH;
						_g_object_unref0 (fd_b);
						_g_object_unref0 (_fd_b_it);
						_g_object_unref0 (fd_a);
						_g_object_unref0 (_fd_a_it);
						_g_object_unref0 (set_b);
						_g_object_unref0 (set_a);
						return;
					}
					_g_object_unref0 (fd_b);
				}
				_g_object_unref0 (_fd_b_it);
			}
			_g_object_unref0 (fd_a);
		}
		_g_object_unref0 (_fd_a_it);
	}
	_g_object_unref0 (set_b);
	_g_object_unref0 (set_a);
}


/**
   * Keep in sync with Folks.MatchResult.
   *
   * @since 0.5.0
   */
gchar* folks_potential_match_result_to_string (FolksMatchResult _result_) {
	gchar* result = NULL;
	gchar* _tmp0_;
	gchar* match_level;
	_tmp0_ = g_strdup ("");
	match_level = _tmp0_;
	switch (_result_) {
		case FOLKS_MATCH_RESULT_VERY_LOW:
		{
			gchar* _tmp1_;
			_tmp1_ = g_strdup ("very low");
			_g_free0 (match_level);
			match_level = _tmp1_;
			break;
		}
		case FOLKS_MATCH_RESULT_LOW:
		{
			gchar* _tmp2_;
			_tmp2_ = g_strdup ("low");
			_g_free0 (match_level);
			match_level = _tmp2_;
			break;
		}
		case FOLKS_MATCH_RESULT_MEDIUM:
		{
			gchar* _tmp3_;
			_tmp3_ = g_strdup ("medium");
			_g_free0 (match_level);
			match_level = _tmp3_;
			break;
		}
		case FOLKS_MATCH_RESULT_HIGH:
		{
			gchar* _tmp4_;
			_tmp4_ = g_strdup ("high");
			_g_free0 (match_level);
			match_level = _tmp4_;
			break;
		}
		case FOLKS_MATCH_RESULT_VERY_HIGH:
		{
			gchar* _tmp5_;
			_tmp5_ = g_strdup ("very high");
			_g_free0 (match_level);
			match_level = _tmp5_;
			break;
		}
		default:
		break;
	}
	result = match_level;
	return result;
}


static void _folks_potential_match_name_similarity (FolksPotentialMatch* self) {
	FolksStructuredName* _tmp0_ = NULL;
	FolksStructuredName* _tmp1_;
	FolksStructuredName* a;
	FolksStructuredName* _tmp2_ = NULL;
	FolksStructuredName* _tmp3_;
	FolksStructuredName* b;
	gdouble similarity;
	const gchar* _tmp4_ = NULL;
	const gchar* _tmp5_ = NULL;
	gboolean _tmp6_;
	const gchar* _tmp7_ = NULL;
	const gchar* _tmp8_ = NULL;
	gboolean _tmp9_;
	gboolean _tmp10_ = FALSE;
	g_return_if_fail (self != NULL);
	_tmp0_ = folks_name_details_get_structured_name ((FolksNameDetails*) self->priv->_individual_a);
	_tmp1_ = _g_object_ref0 (_tmp0_);
	a = _tmp1_;
	_tmp2_ = folks_name_details_get_structured_name ((FolksNameDetails*) self->priv->_individual_b);
	_tmp3_ = _g_object_ref0 (_tmp2_);
	b = _tmp3_;
	similarity = 0.0;
	_tmp4_ = folks_name_details_get_nickname ((FolksNameDetails*) self->priv->_individual_a);
	_tmp5_ = folks_name_details_get_nickname ((FolksNameDetails*) self->priv->_individual_b);
	_tmp6_ = _folks_potential_match_look_alike (self, _tmp4_, _tmp5_);
	if (_tmp6_) {
		similarity = similarity + 0.20;
	}
	_tmp7_ = folks_name_details_get_full_name ((FolksNameDetails*) self->priv->_individual_a);
	_tmp8_ = folks_name_details_get_full_name ((FolksNameDetails*) self->priv->_individual_b);
	_tmp9_ = _folks_potential_match_look_alike (self, _tmp7_, _tmp8_);
	if (_tmp9_) {
		similarity = similarity + 0.70;
	}
	if (a != NULL) {
		_tmp10_ = b != NULL;
	} else {
		_tmp10_ = FALSE;
	}
	if (_tmp10_) {
		gboolean _tmp11_ = FALSE;
		gboolean _tmp12_;
		const gchar* _tmp14_ = NULL;
		const gchar* _tmp15_ = NULL;
		gboolean _tmp16_;
		gboolean _tmp17_ = FALSE;
		const gchar* _tmp18_ = NULL;
		const gchar* _tmp19_ = NULL;
		gboolean _tmp20_;
		const gchar* _tmp24_ = NULL;
		const gchar* _tmp25_ = NULL;
		gboolean _tmp26_;
		const gchar* _tmp27_ = NULL;
		const gchar* _tmp28_ = NULL;
		gboolean _tmp29_;
		const gchar* _tmp30_ = NULL;
		const gchar* _tmp31_ = NULL;
		gboolean _tmp32_;
		_tmp12_ = folks_structured_name_is_empty (a);
		if (_tmp12_ == FALSE) {
			gboolean _tmp13_;
			_tmp13_ = folks_structured_name_equal (a, b);
			_tmp11_ = _tmp13_;
		} else {
			_tmp11_ = FALSE;
		}
		if (_tmp11_) {
			self->priv->_result = FOLKS_MATCH_RESULT_HIGH;
			_g_object_unref0 (b);
			_g_object_unref0 (a);
			return;
		}
		_tmp14_ = folks_structured_name_get_given_name (a);
		_tmp15_ = folks_structured_name_get_given_name (b);
		_tmp16_ = _folks_utils_str_equal_safe (_tmp14_, _tmp15_);
		if (_tmp16_) {
			similarity = similarity + 0.20;
		}
		_tmp18_ = folks_structured_name_get_family_name (a);
		_tmp19_ = folks_structured_name_get_family_name (b);
		_tmp20_ = _folks_potential_match_look_alike (self, _tmp18_, _tmp19_);
		if (_tmp20_) {
			const gchar* _tmp21_ = NULL;
			const gchar* _tmp22_ = NULL;
			gboolean _tmp23_;
			_tmp21_ = folks_structured_name_get_given_name (a);
			_tmp22_ = folks_structured_name_get_given_name (b);
			_tmp23_ = _folks_potential_match_look_alike (self, _tmp21_, _tmp22_);
			_tmp17_ = _tmp23_;
		} else {
			_tmp17_ = FALSE;
		}
		if (_tmp17_) {
			similarity = similarity + 0.40;
		}
		_tmp24_ = folks_structured_name_get_additional_names (a);
		_tmp25_ = folks_structured_name_get_additional_names (b);
		_tmp26_ = _folks_utils_str_equal_safe (_tmp24_, _tmp25_);
		if (_tmp26_) {
			similarity = similarity + 0.5;
		}
		_tmp27_ = folks_structured_name_get_prefixes (a);
		_tmp28_ = folks_structured_name_get_prefixes (b);
		_tmp29_ = _folks_utils_str_equal_safe (_tmp27_, _tmp28_);
		if (_tmp29_) {
			similarity = similarity + 0.5;
		}
		_tmp30_ = folks_structured_name_get_suffixes (a);
		_tmp31_ = folks_structured_name_get_suffixes (b);
		_tmp32_ = _folks_utils_str_equal_safe (_tmp30_, _tmp31_);
		if (_tmp32_) {
			similarity = similarity + 0.5;
		}
	}
	g_debug ("potential-match.vala:214: [name_similarity] Got %f\n", similarity);
	if (similarity >= folks_potential_match__DIST_THRESHOLD) {
		FolksMatchResult _tmp33_;
		_tmp33_ = _folks_potential_match_inc_match_level (self, self->priv->_result, 2);
		self->priv->_result = _tmp33_;
	}
	_g_object_unref0 (b);
	_g_object_unref0 (a);
}


/**
   * Number of equal IM addresses between two individuals.
   *
   * @since 0.5.0
   */
void _folks_potential_match_inspect_im_addresses (FolksPotentialMatch* self) {
	g_return_if_fail (self != NULL);
	{
		GeeMultiMap* _tmp0_ = NULL;
		GeeSet* _tmp1_ = NULL;
		GeeSet* _tmp2_;
		GeeIterator* _tmp3_ = NULL;
		GeeIterator* _tmp4_;
		GeeIterator* _proto_it;
		_tmp0_ = folks_im_details_get_im_addresses ((FolksImDetails*) self->priv->_individual_a);
		_tmp1_ = gee_multi_map_get_keys (_tmp0_);
		_tmp2_ = _tmp1_;
		_tmp3_ = gee_iterable_iterator ((GeeIterable*) _tmp2_);
		_tmp4_ = _tmp3_;
		_g_object_unref0 (_tmp2_);
		_proto_it = _tmp4_;
		while (TRUE) {
			gboolean _tmp5_;
			gpointer _tmp6_ = NULL;
			gchar* proto;
			GeeMultiMap* _tmp7_ = NULL;
			GeeCollection* _tmp8_ = NULL;
			GeeCollection* addrs_a;
			GeeMultiMap* _tmp9_ = NULL;
			GeeCollection* _tmp10_ = NULL;
			GeeCollection* addrs_b;
			_tmp5_ = gee_iterator_next (_proto_it);
			if (!_tmp5_) {
				break;
			}
			_tmp6_ = gee_iterator_get (_proto_it);
			proto = (gchar*) _tmp6_;
			_tmp7_ = folks_im_details_get_im_addresses ((FolksImDetails*) self->priv->_individual_a);
			_tmp8_ = gee_multi_map_get (_tmp7_, proto);
			addrs_a = _tmp8_;
			_tmp9_ = folks_im_details_get_im_addresses ((FolksImDetails*) self->priv->_individual_b);
			_tmp10_ = gee_multi_map_get (_tmp9_, proto);
			addrs_b = _tmp10_;
			{
				GeeIterator* _tmp11_ = NULL;
				GeeIterator* _im_a_it;
				_tmp11_ = gee_iterable_iterator ((GeeIterable*) addrs_a);
				_im_a_it = _tmp11_;
				while (TRUE) {
					gboolean _tmp12_;
					gpointer _tmp13_ = NULL;
					gchar* im_a;
					gboolean _tmp14_;
					_tmp12_ = gee_iterator_next (_im_a_it);
					if (!_tmp12_) {
						break;
					}
					_tmp13_ = gee_iterator_get (_im_a_it);
					im_a = (gchar*) _tmp13_;
					_tmp14_ = gee_collection_contains (addrs_b, im_a);
					if (_tmp14_) {
						self->priv->_result = FOLKS_MATCH_RESULT_HIGH;
						_g_free0 (im_a);
						_g_object_unref0 (_im_a_it);
						_g_object_unref0 (addrs_b);
						_g_object_unref0 (addrs_a);
						_g_free0 (proto);
						_g_object_unref0 (_proto_it);
						return;
					}
					_g_free0 (im_a);
				}
				_g_object_unref0 (_im_a_it);
			}
			_g_object_unref0 (addrs_b);
			_g_object_unref0 (addrs_a);
			_g_free0 (proto);
		}
		_g_object_unref0 (_proto_it);
	}
}


/**
   * Inspect email addresses.
   *
   * @since 0.5.0
   */
static void _folks_potential_match_inspect_emails (FolksPotentialMatch* self) {
	GeeSet* _tmp0_ = NULL;
	GeeSet* _tmp1_;
	GeeSet* set_a;
	GeeSet* _tmp2_ = NULL;
	GeeSet* _tmp3_;
	GeeSet* set_b;
	g_return_if_fail (self != NULL);
	_tmp0_ = folks_email_details_get_email_addresses ((FolksEmailDetails*) self->priv->_individual_a);
	_tmp1_ = _g_object_ref0 (_tmp0_);
	set_a = _tmp1_;
	_tmp2_ = folks_email_details_get_email_addresses ((FolksEmailDetails*) self->priv->_individual_b);
	_tmp3_ = _g_object_ref0 (_tmp2_);
	set_b = _tmp3_;
	{
		GeeIterator* _tmp4_ = NULL;
		GeeIterator* _fd_a_it;
		_tmp4_ = gee_iterable_iterator ((GeeIterable*) set_a);
		_fd_a_it = _tmp4_;
		while (TRUE) {
			gboolean _tmp5_;
			gpointer _tmp6_ = NULL;
			FolksFieldDetails* fd_a;
			_tmp5_ = gee_iterator_next (_fd_a_it);
			if (!_tmp5_) {
				break;
			}
			_tmp6_ = gee_iterator_get (_fd_a_it);
			fd_a = (FolksFieldDetails*) _tmp6_;
			{
				GeeIterator* _tmp7_ = NULL;
				GeeIterator* _fd_b_it;
				_tmp7_ = gee_iterable_iterator ((GeeIterable*) set_b);
				_fd_b_it = _tmp7_;
				while (TRUE) {
					gboolean _tmp8_;
					gpointer _tmp9_ = NULL;
					FolksFieldDetails* fd_b;
					const gchar* _tmp10_ = NULL;
					gchar** _tmp11_;
					gchar** _tmp12_ = NULL;
					gchar** email_split_a;
					gint email_split_a_length1;
					gint _email_split_a_size_;
					const gchar* _tmp13_ = NULL;
					gchar** _tmp14_;
					gchar** _tmp15_ = NULL;
					gchar** email_split_b;
					gint email_split_b_length1;
					gint _email_split_b_size_;
					const gchar* _tmp16_ = NULL;
					const gchar* _tmp17_ = NULL;
					_tmp8_ = gee_iterator_next (_fd_b_it);
					if (!_tmp8_) {
						break;
					}
					_tmp9_ = gee_iterator_get (_fd_b_it);
					fd_b = (FolksFieldDetails*) _tmp9_;
					_tmp10_ = folks_field_details_get_value (fd_a);
					_tmp12_ = _tmp11_ = g_strsplit (_tmp10_, "@", 0);
					email_split_a = _tmp12_;
					email_split_a_length1 = _vala_array_length (_tmp11_);
					_email_split_a_size_ = _vala_array_length (_tmp11_);
					_tmp13_ = folks_field_details_get_value (fd_b);
					_tmp15_ = _tmp14_ = g_strsplit (_tmp13_, "@", 0);
					email_split_b = _tmp15_;
					email_split_b_length1 = _vala_array_length (_tmp14_);
					_email_split_b_size_ = _vala_array_length (_tmp14_);
					_tmp16_ = folks_field_details_get_value (fd_a);
					_tmp17_ = folks_field_details_get_value (fd_b);
					if (g_strcmp0 (_tmp16_, _tmp17_) == 0) {
						gboolean _tmp18_;
						_tmp18_ = gee_collection_contains ((GeeCollection*) folks_potential_match_known_email_aliases, email_split_a[0]);
						if (_tmp18_ == TRUE) {
							if (self->priv->_result < FOLKS_MATCH_RESULT_HIGH) {
								self->priv->_result = FOLKS_MATCH_RESULT_LOW;
							}
						} else {
							self->priv->_result = FOLKS_MATCH_RESULT_HIGH;
							email_split_b = (_vala_array_free (email_split_b, email_split_b_length1, (GDestroyNotify) g_free), NULL);
							email_split_a = (_vala_array_free (email_split_a, email_split_a_length1, (GDestroyNotify) g_free), NULL);
							_g_object_unref0 (fd_b);
							_g_object_unref0 (_fd_b_it);
							_g_object_unref0 (fd_a);
							_g_object_unref0 (_fd_a_it);
							_g_object_unref0 (set_b);
							_g_object_unref0 (set_a);
							return;
						}
					} else {
						gchar** _tmp19_;
						gchar** _tmp20_ = NULL;
						gchar** tokens_a;
						gint tokens_a_length1;
						gint _tokens_a_size_;
						gchar** _tmp21_;
						gchar** _tmp22_ = NULL;
						gchar** tokens_b;
						gint tokens_b_length1;
						gint _tokens_b_size_;
						gboolean _tmp23_;
						_tmp20_ = _tmp19_ = g_strsplit_set (email_split_a[0], FOLKS_POTENTIAL_MATCH__SEPARATORS, 0);
						tokens_a = _tmp20_;
						tokens_a_length1 = _vala_array_length (_tmp19_);
						_tokens_a_size_ = _vala_array_length (_tmp19_);
						_tmp22_ = _tmp21_ = g_strsplit_set (email_split_b[0], FOLKS_POTENTIAL_MATCH__SEPARATORS, 0);
						tokens_b = _tmp22_;
						tokens_b_length1 = _vala_array_length (_tmp21_);
						_tokens_b_size_ = _vala_array_length (_tmp21_);
						_tmp23_ = _folks_potential_match_check_initials_expansion (self, tokens_a, tokens_a_length1, tokens_b, tokens_b_length1);
						if (_tmp23_) {
							self->priv->_result = FOLKS_MATCH_RESULT_MEDIUM;
						} else {
							gboolean _tmp24_;
							_tmp24_ = _folks_potential_match_match_tokens (self, tokens_a, tokens_a_length1, tokens_b, tokens_b_length1);
							if (_tmp24_) {
								self->priv->_result = FOLKS_MATCH_RESULT_MEDIUM;
							}
						}
						tokens_b = (_vala_array_free (tokens_b, tokens_b_length1, (GDestroyNotify) g_free), NULL);
						tokens_a = (_vala_array_free (tokens_a, tokens_a_length1, (GDestroyNotify) g_free), NULL);
					}
					email_split_b = (_vala_array_free (email_split_b, email_split_b_length1, (GDestroyNotify) g_free), NULL);
					email_split_a = (_vala_array_free (email_split_a, email_split_a_length1, (GDestroyNotify) g_free), NULL);
					_g_object_unref0 (fd_b);
				}
				_g_object_unref0 (_fd_b_it);
			}
			_g_object_unref0 (fd_a);
		}
		_g_object_unref0 (_fd_a_it);
	}
	_g_object_unref0 (set_b);
	_g_object_unref0 (set_a);
}


static gboolean _folks_potential_match_check_initials_expansion (FolksPotentialMatch* self, gchar** tokens_a, int tokens_a_length1, gchar** tokens_b, int tokens_b_length1) {
	gboolean result = FALSE;
	gboolean _tmp0_ = FALSE;
	g_return_val_if_fail (self != NULL, FALSE);
	if (tokens_a_length1 > tokens_b_length1) {
		_tmp0_ = tokens_b_length1 == 1;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		gboolean _tmp1_;
		_tmp1_ = _folks_potential_match_do_check_initials_expansion (self, tokens_a, tokens_a_length1, tokens_b[0]);
		result = _tmp1_;
		return result;
	} else {
		gboolean _tmp2_ = FALSE;
		if (tokens_b_length1 > tokens_a_length1) {
			_tmp2_ = tokens_a_length1 == 1;
		} else {
			_tmp2_ = FALSE;
		}
		if (_tmp2_) {
			gboolean _tmp3_;
			_tmp3_ = _folks_potential_match_do_check_initials_expansion (self, tokens_b, tokens_b_length1, tokens_a[0]);
			result = _tmp3_;
			return result;
		}
	}
	result = FALSE;
	return result;
}


static gchar string_get (const gchar* self, glong index) {
	gchar result = '\0';
	g_return_val_if_fail (self != NULL, '\0');
	result = ((gchar*) self)[index];
	return result;
}


static gboolean _folks_potential_match_do_check_initials_expansion (FolksPotentialMatch* self, gchar** expanded_name, int expanded_name_length1, const gchar* initials) {
	gboolean result = FALSE;
	gint _tmp0_;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (initials != NULL, FALSE);
	_tmp0_ = strlen (initials);
	if (expanded_name_length1 != _tmp0_) {
		result = FALSE;
		return result;
	}
	{
		gint i;
		i = 0;
		{
			gboolean _tmp1_;
			_tmp1_ = TRUE;
			while (TRUE) {
				gchar _tmp2_;
				gchar _tmp3_;
				if (!_tmp1_) {
					i++;
				}
				_tmp1_ = FALSE;
				if (!(i < expanded_name_length1)) {
					break;
				}
				_tmp2_ = string_get (expanded_name[i], (glong) 0);
				_tmp3_ = string_get (initials, (glong) i);
				if (_tmp2_ != _tmp3_) {
					result = FALSE;
					return result;
				}
			}
		}
	}
	result = TRUE;
	return result;
}


static gboolean _folks_potential_match_match_tokens (FolksPotentialMatch* self, gchar** tokens_a, int tokens_a_length1, gchar** tokens_b, int tokens_b_length1) {
	gboolean result = FALSE;
	g_return_val_if_fail (self != NULL, FALSE);
	if (tokens_a_length1 > tokens_b_length1) {
		gboolean _tmp0_;
		_tmp0_ = _folks_potential_match_do_match_tokens (self, tokens_a, tokens_a_length1, tokens_b, tokens_b_length1);
		result = _tmp0_;
		return result;
	} else {
		gboolean _tmp1_;
		_tmp1_ = _folks_potential_match_do_match_tokens (self, tokens_b, tokens_b_length1, tokens_a, tokens_a_length1);
		result = _tmp1_;
		return result;
	}
}


static gboolean _folks_potential_match_do_match_tokens (FolksPotentialMatch* self, gchar** bigger_set, int bigger_set_length1, gchar** smaller_set, int smaller_set_length1) {
	gboolean result = FALSE;
	g_return_val_if_fail (self != NULL, FALSE);
	{
		gint i;
		i = 0;
		{
			gboolean _tmp0_;
			_tmp0_ = TRUE;
			while (TRUE) {
				if (!_tmp0_) {
					i++;
				}
				_tmp0_ = FALSE;
				if (!(i < smaller_set_length1)) {
					break;
				}
				{
					gint j;
					j = 0;
					{
						gboolean _tmp1_;
						_tmp1_ = TRUE;
						while (TRUE) {
							if (!_tmp1_) {
								j++;
							}
							_tmp1_ = FALSE;
							if (!(j < bigger_set_length1)) {
								break;
							}
							if (g_strcmp0 (smaller_set[i], bigger_set[j]) == 0) {
								result = TRUE;
								return result;
							}
						}
					}
				}
			}
		}
	}
	result = FALSE;
	return result;
}


static FolksMatchResult _folks_potential_match_inc_match_level (FolksPotentialMatch* self, FolksMatchResult current_level, gint times) {
	FolksMatchResult result = 0;
	FolksMatchResult ret;
	g_return_val_if_fail (self != NULL, 0);
	ret = current_level + times;
	if (ret > FOLKS_MATCH_RESULT_MAX) {
		ret = FOLKS_MATCH_RESULT_MAX;
	}
	result = ret;
	return result;
}


static gboolean _folks_potential_match_look_alike (FolksPotentialMatch* self, const gchar* a, const gchar* b) {
	gboolean result = FALSE;
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gdouble _tmp2_;
	gboolean alike;
	g_return_val_if_fail (self != NULL, FALSE);
	if (a == NULL) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = b == NULL;
	}
	if (_tmp0_) {
		result = FALSE;
		return result;
	}
	_tmp2_ = folks_potential_match_jaro_dist (self, a, b);
	if (_tmp2_ >= folks_potential_match__DIST_THRESHOLD) {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = FALSE;
	}
	alike = _tmp1_;
	result = alike;
	return result;
}


gdouble folks_potential_match_jaro_dist (FolksPotentialMatch* self, const gchar* s1, const gchar* s2) {
	gdouble result = 0.0;
	gdouble distance = 0.0;
	gint _tmp0_ = 0;
	gint _tmp1_;
	gint _tmp2_;
	gint max;
	gint max_dist;
	gdouble t = 0.0;
	gdouble _tmp5_;
	gint _tmp6_;
	gdouble m;
	gint _tmp7_;
	gdouble len_s1;
	gint _tmp8_;
	gdouble len_s2;
	gdouble a;
	gdouble b;
	gdouble c;
	g_return_val_if_fail (self != NULL, 0.0);
	g_return_val_if_fail (s1 != NULL, 0.0);
	g_return_val_if_fail (s2 != NULL, 0.0);
	_tmp1_ = strlen (s1);
	_tmp2_ = strlen (s2);
	if (_tmp1_ > _tmp2_) {
		gint _tmp3_;
		_tmp3_ = strlen (s1);
		_tmp0_ = _tmp3_;
	} else {
		gint _tmp4_;
		_tmp4_ = strlen (s2);
		_tmp0_ = _tmp4_;
	}
	max = _tmp0_;
	max_dist = (max / 2) - 1;
	_tmp6_ = _folks_potential_match_matches (self, s1, s2, max_dist, &_tmp5_);
	t = _tmp5_;
	m = (gdouble) _tmp6_;
	_tmp7_ = strlen (s1);
	len_s1 = (gdouble) _tmp7_;
	_tmp8_ = strlen (s2);
	len_s2 = (gdouble) _tmp8_;
	a = m / len_s1;
	b = m / len_s2;
	c = (gdouble) 0;
	if (((gint) m) > 0) {
		c = (m - t) / m;
	}
	distance = (1.0 / 3.0) * ((a + b) + c);
	g_debug ("potential-match.vala:410: [jaro_dist] Distance for %s and %s: %f\n", s1, s2, distance);
	result = distance;
	return result;
}


static gchar* string_slice (const gchar* self, glong start, glong end) {
	gchar* result = NULL;
	gint _tmp0_;
	glong string_length;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	gchar* _tmp3_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = strlen (self);
	string_length = (glong) _tmp0_;
	if (start < 0) {
		start = string_length + start;
	}
	if (end < 0) {
		end = string_length + end;
	}
	if (start >= 0) {
		_tmp1_ = start <= string_length;
	} else {
		_tmp1_ = FALSE;
	}
	g_return_val_if_fail (_tmp1_, NULL);
	if (end >= 0) {
		_tmp2_ = end <= string_length;
	} else {
		_tmp2_ = FALSE;
	}
	g_return_val_if_fail (_tmp2_, NULL);
	g_return_val_if_fail (start <= end, NULL);
	_tmp3_ = g_strndup (((gchar*) self) + start, (gsize) (end - start));
	result = _tmp3_;
	return result;
}


static gint _folks_potential_match_matches (FolksPotentialMatch* self, const gchar* s1, const gchar* s2, gint max_dist, gdouble* t) {
	gdouble _t = 0.0;
	gint result = 0;
	gint matches;
	g_return_val_if_fail (self != NULL, 0);
	g_return_val_if_fail (s1 != NULL, 0);
	g_return_val_if_fail (s2 != NULL, 0);
	matches = 0;
	_t = 0.0;
	{
		gint i;
		i = 0;
		{
			gboolean _tmp0_;
			_tmp0_ = TRUE;
			while (TRUE) {
				gint _tmp1_;
				gchar* _tmp2_ = NULL;
				gchar* look_for;
				gint _tmp3_;
				gint contains;
				if (!_tmp0_) {
					i++;
				}
				_tmp0_ = FALSE;
				_tmp1_ = strlen (s1);
				if (!(i < _tmp1_)) {
					break;
				}
				_tmp2_ = string_slice (s1, (glong) i, (glong) (i + 1));
				look_for = _tmp2_;
				_tmp3_ = _folks_potential_match_contains (self, s2, look_for, i, max_dist);
				contains = _tmp3_;
				if (contains >= 0) {
					matches++;
					if (contains > 0) {
						_t = _t + 1.0;
					}
				}
				_g_free0 (look_for);
			}
		}
	}
	g_debug ("potential-match.vala:434: %s and %s have %d matches and %f / 2 transpo" \
"sitions\n", s1, s2, matches, _t);
	_t = _t / 2.0;
	result = matches;
	if (t) {
		*t = _t;
	}
	return result;
}


static gint _folks_potential_match_contains (FolksPotentialMatch* self, const gchar* haystack, const gchar* c, gint pos, gint max_dist) {
	gint result = 0;
	gboolean _tmp0_ = FALSE;
	gint _tmp1_;
	g_return_val_if_fail (self != NULL, 0);
	g_return_val_if_fail (haystack != NULL, 0);
	g_return_val_if_fail (c != NULL, 0);
	_tmp1_ = strlen (haystack);
	if (pos < _tmp1_) {
		gchar* _tmp2_ = NULL;
		gchar* _tmp3_;
		_tmp2_ = string_slice (haystack, (glong) pos, (glong) (pos + 1));
		_tmp3_ = _tmp2_;
		_tmp0_ = g_strcmp0 (_tmp3_, c) == 0;
		_g_free0 (_tmp3_);
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		result = 0;
		return result;
	}
	{
		gint i;
		i = pos - max_dist;
		{
			gboolean _tmp4_;
			_tmp4_ = TRUE;
			while (TRUE) {
				gboolean _tmp5_ = FALSE;
				gchar* _tmp7_ = NULL;
				gchar* str;
				if (!_tmp4_) {
					i++;
				}
				_tmp4_ = FALSE;
				if (!(i <= (pos + max_dist))) {
					break;
				}
				if (i < 0) {
					_tmp5_ = TRUE;
				} else {
					gint _tmp6_;
					_tmp6_ = strlen (haystack);
					_tmp5_ = i >= _tmp6_;
				}
				if (_tmp5_) {
					continue;
				}
				_tmp7_ = string_slice (haystack, (glong) i, (glong) (i + 1));
				str = _tmp7_;
				if (g_strcmp0 (str, c) == 0) {
					gint _tmp8_;
					_tmp8_ = abs (pos - i);
					result = _tmp8_;
					_g_free0 (str);
					return result;
				}
				_g_free0 (str);
			}
		}
	}
	result = -1;
	return result;
}


static void folks_potential_match_class_init (FolksPotentialMatchClass * klass) {
	folks_potential_match_parent_class = g_type_class_peek_parent (klass);
	g_type_class_add_private (klass, sizeof (FolksPotentialMatchPrivate));
	G_OBJECT_CLASS (klass)->finalize = folks_potential_match_finalize;
}


static void folks_potential_match_instance_init (FolksPotentialMatch * self) {
	self->priv = FOLKS_POTENTIAL_MATCH_GET_PRIVATE (self);
}


static void folks_potential_match_finalize (GObject* obj) {
	FolksPotentialMatch * self;
	self = FOLKS_POTENTIAL_MATCH (obj);
	_g_object_unref0 (self->priv->_individual_a);
	_g_object_unref0 (self->priv->_individual_b);
	G_OBJECT_CLASS (folks_potential_match_parent_class)->finalize (obj);
}


/**
 * This class provides functionality to explore a potential match between
 * two individuals.
 *
 * @since 0.5.0
 */
GType folks_potential_match_get_type (void) {
	static volatile gsize folks_potential_match_type_id__volatile = 0;
	if (g_once_init_enter (&folks_potential_match_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (FolksPotentialMatchClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) folks_potential_match_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (FolksPotentialMatch), 0, (GInstanceInitFunc) folks_potential_match_instance_init, NULL };
		GType folks_potential_match_type_id;
		folks_potential_match_type_id = g_type_register_static (G_TYPE_OBJECT, "FolksPotentialMatch", &g_define_type_info, 0);
		g_once_init_leave (&folks_potential_match_type_id__volatile, folks_potential_match_type_id);
	}
	return folks_potential_match_type_id__volatile;
}


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


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


static gint _vala_array_length (gpointer array) {
	int length;
	length = 0;
	if (array) {
		while (((gpointer*) array)[length]) {
			length++;
		}
	}
	return length;
}



