/*
     This file is part of GNUnet.
     Copyright (C) 2013-2014 GNUnet e.V.

     GNUnet is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published
     by the Free Software Foundation; either version 3, or (at your
     option) any later version.

     GNUnet 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
     General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with GNUnet; see the file COPYING.  If not, write to the
     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     Boston, MA 02110-1301, USA.
*/

/**
 * @file src/conversation/gnunet-conversation-gtk_egos.c
 * @brief Manages the list of egos for selecting our caller-ID
 * @author yids
 * @author hark
 * @author Christian Grothoff
 */
#include "gnunet-conversation-gtk.h"
#include "gnunet-conversation-gtk_egos.h"


/**
 * Columns in the #ego_liststore.
 */
enum EgoListstoreValues
{
  /**
   * Human-readable name of the ego.
   */
  EGO_LS_NAME = 0,

  /**
   * Handel to the ego (of type `struct GNUNET_IDENTITY_Ego *ego`).
   */
  EGO_LS_EGO = 1
};


/**
 * Handle to identity service.
 */
static struct GNUNET_IDENTITY_Handle *id;

/**
 * list of egos
 */
static GtkListStore *ego_liststore;

/**
 * Default ego to pre-select.
 */
static char *default_ego;


/**
 * Obtain the currently selected ego.
 *
 * @return NULL if no ego is selected
 */
struct GNUNET_IDENTITY_Ego *
GCG_EGOS_get_selected_ego ()
{
  struct GNUNET_IDENTITY_Ego *ego;
  GtkTreeIter iter;
  GtkComboBox *cb;

  cb = GTK_COMBO_BOX (
    GCG_get_main_window_object ("gnunet_conversation_gtk_ego_combobox"));
  if (! gtk_combo_box_get_active_iter (cb, &iter))
    return NULL;
  gtk_tree_model_get (GTK_TREE_MODEL (ego_liststore),
                      &iter,
                      EGO_LS_EGO,
                      &ego,
                      -1);
  return ego;
}


/**
 * Function called by identity service with information about egos.
 *
 * @param cls NULL
 * @param ego ego handle
 * @param ctx unused
 * @param name name of the ego
 */
static void
identity_cb (void *cls,
             struct GNUNET_IDENTITY_Ego *ego,
             void **ctx,
             const char *name)
{
  GtkTreeIter iter;
  GtkTreeIter iter2;
  GtkTreeRowReference *rr;
  GtkTreePath *path;
  GtkComboBox *cb;

  if (NULL == ctx)
  {
    /* end of initial iteration, ignore */
    return;
  }
  rr = *ctx;
  if (NULL == rr)
  {
    /* new identity */
    GNUNET_assert (NULL != name);
    gtk_list_store_insert_with_values (ego_liststore,
                                       &iter,
                                       -1,
                                       EGO_LS_NAME,
                                       name,
                                       EGO_LS_EGO,
                                       ego,
                                       -1);
    cb = GTK_COMBO_BOX (
      GCG_get_main_window_object ("gnunet_conversation_gtk_ego_combobox"));
    if ((! gtk_combo_box_get_active_iter (cb, &iter2)) &&
        ((NULL == default_ego) || (0 == strcmp (name, default_ego))))
    {
      /* found the ego that we were supposed to use by default, select
         it! */
      gtk_combo_box_set_active_iter (cb, &iter);
    }
    path = gtk_tree_model_get_path (GTK_TREE_MODEL (ego_liststore), &iter);
    rr = gtk_tree_row_reference_new (GTK_TREE_MODEL (ego_liststore), path);
    gtk_tree_path_free (path);
    *ctx = rr;
    return;
  }
  /* existing ego, locate and execute rename/delete */
  path = gtk_tree_row_reference_get_path (rr);
  GNUNET_assert (
    gtk_tree_model_get_iter (GTK_TREE_MODEL (ego_liststore), &iter, path));
  gtk_tree_path_free (path);
  if (NULL == name)
  {
    /* deletion operation */
    gtk_tree_row_reference_free (rr);
    *ctx = NULL;
    gtk_list_store_remove (ego_liststore, &iter);
    return;
  }
  /* rename operation */
  gtk_list_store_set (ego_liststore, &iter, EGO_LS_NAME, &name, -1);
}


/**
 * User clicked the "copy" button.  Copy address information
 * for our current phone to the clipboard.
 *
 * @param button the button
 * @param user_data builder (unused)
 */
void
gnunet_conversation_gtk_ego_copy_button_clicked_cb (GtkButton *button,
                                                    gpointer user_data)
{
  struct GNUNET_IDENTITY_Ego *ego;
  const gchar *label;
  struct GNUNET_IDENTITY_PublicKey pub;
  const char *zkey;
  char *uri;
  GtkClipboard *cb;

  label = gtk_entry_get_text (GTK_ENTRY (
                                GCG_get_main_window_object (
                                  "gnunet_conversation_gtk_ego_label_entry")));
  GNUNET_break ((NULL != label) && (0 != strlen (label)));
  ego = GCG_EGOS_get_selected_ego ();
  GNUNET_break (NULL != ego);
  GNUNET_IDENTITY_ego_get_public_key (ego, &pub);
  zkey = GNUNET_GNSRECORD_pkey_to_zkey (&pub);
  GNUNET_asprintf (&uri, "gnunet://gns/%s.%s/", label, zkey);
  cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
  gtk_clipboard_set_text (cb, uri, -1);
  gtk_clipboard_store (cb);
  GNUNET_free (uri);
}


/**
 * Initialize the ego list
 *
 * @param ego_name default ego to pre-select
 */
void
GCG_EGOS_init (const char *ego_name)
{
  if (NULL != ego_name)
    default_ego = GNUNET_strdup (ego_name);
  ego_liststore = GTK_LIST_STORE (
    GCG_get_main_window_object ("gnunet_conversation_gtk_ego_liststore"));
  id = GNUNET_IDENTITY_connect (GCG_get_configuration (), &identity_cb, NULL);
}


/**
 * Shutdown the ego list
 */
void
GCG_EGOS_shutdown ()
{
  if (NULL != id)
  {
    GNUNET_IDENTITY_disconnect (id);
    id = NULL;
  }
  if (NULL != default_ego)
  {
    GNUNET_free (default_ego);
    default_ego = NULL;
  }
}


/* end of gnunet-conversation-gtk_egos.c */
