#include <glib.h>

#include <folks/folks.h>
#include <folks/folks-telepathy.h>

#include <telepathy-glib/telepathy-glib.h>

#define ACCOUNT TP_ACCOUNT_OBJECT_PATH_BASE "gabble/jabber/cassidy_40jabber_2ebelnet_2ebe0"
#define CONTACT_ID "noinroster@jabber.org"

#define DEBUG

static GMainLoop *loop = NULL;

static void
check_individual (FolksIndividual *individual)
{
  TpContact *contact = NULL;
  GeeSet *personas;
  GeeIterator *iter;

  personas = folks_individual_get_personas (individual);
  g_assert_cmpuint (gee_collection_get_size (GEE_COLLECTION (personas)), ==, 1);

  iter = gee_iterable_iterator (GEE_ITERABLE (personas));
  while (gee_iterator_next (iter))
    {
      TpfPersona *persona = gee_iterator_get (iter);
      TpContact *contact;

      g_assert (TPF_IS_PERSONA (persona));

      contact = tpf_persona_get_contact (persona);
      g_assert (TP_IS_CONTACT (contact));

      g_assert_cmpstr (tp_contact_get_identifier (contact), ==, CONTACT_ID);

      g_clear_object (&persona);
    }
  g_clear_object (&iter);

  g_print ("check ok\n");
}

static gboolean
idle_cb (gpointer user_data)
{
  FolksIndividual *individual = user_data;

  /* re-check after the get_contact cb: fail */
  check_individual (individual);
  g_main_loop_quit (loop);
  return FALSE;
}

FolksIndividual *
empathy_create_individual_from_tp_contact (TpContact *contact)
{
  GeeSet *personas;
  TpfPersona *persona;
  FolksIndividual *individual;

  persona = tpf_persona_dup_for_contact (contact);
  if (persona == NULL)
    {
      DEBUG ("Failed to get a persona for %s",
          tp_contact_get_identifier (contact));
      return NULL;
    }

  personas = GEE_SET (
      gee_hash_set_new (FOLKS_TYPE_PERSONA, g_object_ref, g_object_unref,
      g_direct_hash, g_direct_equal));

  gee_collection_add (GEE_COLLECTION (personas), persona);

  individual = folks_individual_new (personas);

  g_clear_object (&persona);
  g_clear_object (&personas);

  return individual;
}

static void
get_contact_cb (TpConnection *connection,
    guint n_contacts,
    TpContact * const *contacts,
    const gchar * const *requested_ids,
    GHashTable *failed_id_errors,
    const GError *error,
    gpointer user_data,
    GObject *weak_object)
{
  TpContact *contact;
  FolksIndividual *individual;

  g_assert_no_error (error);
  g_assert_cmpuint (n_contacts, ==, 1);

  contact = contacts[0];

  individual = empathy_create_individual_from_tp_contact (contact);
  g_assert (individual != NULL);

  /* Check if the individual is ok: pass */
  check_individual (individual);

  g_idle_add (idle_cb, individual);
}

static void
am_prepare_cb (GObject *source,
    GAsyncResult *result,
    gpointer user_data)
{
  TpAccountManager *am = (TpAccountManager *) source;
  TpAccount *account;
  TpSimpleClientFactory *factory;
  GError *error = NULL;
  TpContact *contact;
  TpConnection *conn;
  const gchar *id = CONTACT_ID;

  tp_proxy_prepare_finish (source, result, &error);
  g_assert_no_error (error);

  factory = tp_proxy_get_factory (am);

  account = tp_simple_client_factory_ensure_account (factory, ACCOUNT, NULL,
      &error);
  g_assert_no_error (error);

  conn = tp_account_get_connection (account);
  g_assert (conn != NULL);

  tp_connection_get_contacts_by_id (conn, 1, &id, 0, NULL,
      get_contact_cb, NULL, NULL, NULL);
}

int
main (int argc,
    gchar *argv)
{
  guint i;
  TpAccountManager *am;
  TpSimpleClientFactory *factory;

  g_type_init ();

  am = tp_account_manager_dup ();

  factory = tp_proxy_get_factory (am);
  tp_simple_client_factory_add_account_features_varargs (factory,
      TP_ACCOUNT_FEATURE_CONNECTION, NULL);

  tp_proxy_prepare_async (am, NULL, am_prepare_cb, NULL);

  loop = g_main_loop_new (NULL, FALSE);
  g_main_loop_run (loop);
  return 0;
}
