/*
     This file is part of GNUnet.
     Copyright (C) 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_get_label.c
 * @brief logic to import caller ID into address book
 * @author Christian Grothoff
 */
#include "gnunet-conversation-gtk.h"
#include "gnunet-conversation-gtk_egos.h"
#include "gnunet-conversation-gtk_history.h"
#include "gnunet-conversation-gtk_get_label.h"
#include "gnunet-conversation-gtk_import.h"
#include "gnunet-conversation-gtk_log.h"
#include "gnunet-conversation-gtk_phone.h"
#include "gnunet-conversation-gtk_zones.h"


/**
 * Queue entry for the 'check exists' operation.
 */
static struct GNUNET_NAMESTORE_QueueEntry *qe;

/**
 * What is the value we want to publish in the namestore?
 */
static char *target;


/**
 * Called on error communicating with the namestore.
 */
static void
handle_error (void *cls)
{
  qe = NULL;
  GCG_log (_ ("Error communicating with namestore!\n"));
}


/**
 * Process a record that was stored in the namestore.
 *
 * @param cls closure, NULL
 * @param zone private key of the zone; NULL on disconnect
 * @param label label of the records; NULL on disconnect
 * @param rd_count number of entries in @a rd array, 0 if label was deleted
 * @param rd array of records with data to store
 */
static void
handle_existing_records (void *cls,
                         const struct GNUNET_IDENTITY_PrivateKey *zone,
                         const char *label,
                         unsigned int rd_count,
                         const struct GNUNET_GNSRECORD_Data *rd)
{
  GtkBuilder *builder = GTK_BUILDER (cls);
  GtkWidget *b_add;

  qe = NULL;
  if (0 != rd_count)
  {
    GCG_log (_ ("Label `%s' in use\n"), label);
    return;
  }
  b_add = GTK_WIDGET (gtk_builder_get_object (
    builder,
    "gnunet_conversation_gtk_enter_label_dialog_add_button"));
  gtk_widget_set_sensitive (b_add, TRUE);
}


/**
 * The user has edited the label; check if the new label
 * is valid and available and update the sensitivity of
 * the "add" button.
 *
 * @param editable the entry that changed
 * @param user_data our builder
 */
void
gnunet_conversation_gtk_enter_label_entry_changed_cb (GtkEditable *editable,
                                                      gpointer user_data)
{
  GtkBuilder *builder = GTK_BUILDER (user_data);
  GtkEntry *label_entry;
  const gchar *label;
  GtkWidget *b_add;
  struct GNUNET_IDENTITY_Ego *ego;
  const struct GNUNET_IDENTITY_PrivateKey *pkey;
  const char *tld;

  if (NULL != qe)
  {
    GNUNET_NAMESTORE_cancel (qe);
    qe = NULL;
  }
  label_entry = GTK_ENTRY (
    gtk_builder_get_object (builder,
                            ("gnunet_conversation_gtk_enter_label_entry")));
  label = gtk_entry_get_text (label_entry);
  b_add = GTK_WIDGET (gtk_builder_get_object (
    builder,
    "gnunet_conversation_gtk_enter_label_dialog_add_button"));
  gtk_widget_set_sensitive (b_add, FALSE);
  if (GNUNET_OK != GNUNET_DNSPARSER_check_label (label))
  {
    GCG_log (_ ("Invalid label `%s'\n"), label);
    return;
  }
  ego = GCG_ZONES_get_selected_zone (&tld);
  if (NULL == ego)
    return;
  pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
  qe = GNUNET_NAMESTORE_records_lookup (GCG_IMPORT_get_namestore (),
                                        pkey,
                                        label,
                                        &handle_error,
                                        builder,
                                        &handle_existing_records,
                                        builder);
}


/**
 * The user has clicked the "add" button, close the dialog and
 * complete the "add contact" operation.
 *
 * @param button the button
 * @param user_data our builder
 */
void
gnunet_conversation_gtk_enter_label_dialog_add_button_clicked_cb (
  GtkButton *button,
  gpointer *user_data)
{
  GtkBuilder *builder = GTK_BUILDER (user_data);
  GtkWidget *dialog;
  const gchar *label;
  GtkEntry *label_entry;

  label_entry = GTK_ENTRY (
    gtk_builder_get_object (builder,
                            ("gnunet_conversation_gtk_enter_label_entry")));
  label = gtk_entry_get_text (label_entry);
  GSC_add_contact (label, target);
  GNUNET_free (target);
  target = NULL;
  dialog = GTK_WIDGET (
    gtk_builder_get_object (builder,
                            "gnunet_conversation_gtk_enter_label_window"));
  gtk_widget_destroy (GTK_WIDGET (dialog));
  g_object_unref (G_OBJECT (builder));
}


/**
 * The user has clicked the "cancel" button, close the dialog and
 * abort the "add contact" operation.
 *
 * @param button the button
 * @param user_data our builder
 */
void
gnunet_conversation_gtk_enter_label_dialog_cancel_button_clicked_cb (
  GtkButton *button,
  gpointer *user_data)
{
  GtkBuilder *builder = GTK_BUILDER (user_data);
  GtkWidget *dialog;

  dialog = GTK_WIDGET (
    gtk_builder_get_object (builder,
                            "gnunet_conversation_gtk_enter_label_window"));
  GNUNET_free (target);
  target = NULL;
  gtk_widget_destroy (GTK_WIDGET (dialog));
  g_object_unref (G_OBJECT (builder));
}


/**
 * User closed the window of the enter label dialog.
 *
 * @param widget the window
 * @param event the deletion event
 * @param user_data the 'GtkBuilder' of the URI dialog
 * @return FALSE (allow destruction)
 */
gboolean
gnunet_conversation_gtk_enter_label_window_delete_event_cb (GtkWidget *widget,
                                                            GdkEvent *event,
                                                            gpointer user_data)
{
  GtkBuilder *builder = GTK_BUILDER (user_data);

  g_object_unref (G_OBJECT (builder));
  GNUNET_free (target);
  target = NULL;
  return FALSE;
}


/**
 * Obtain the label the user wants to use for a given
 * name and (if successful) add the name to the
 * address book usnig #GSC_add_contact().
 *
 * @param name value to publish (corresponds to CNAME or PKEY record)
 * @param label suggested label (user can change)
 */
void
GSC_get_label_for_name (const char *name, const char *label)
{
  GtkBuilder *builder;
  GtkWidget *dialog;
  GtkWidget *toplevel;
  GtkEntry *label_entry;
  GtkWidget *address_entry;

  builder =
    GNUNET_GTK_get_new_builder ("gnunet_conversation_gtk_enter_label.glade",
                                NULL);
  if (NULL == builder)
  {
    GNUNET_break (0);
    return;
  }
  target = GNUNET_strdup (name);
  label_entry = GTK_ENTRY (
    gtk_builder_get_object (builder,
                            ("gnunet_conversation_gtk_enter_label_entry")));
  gtk_entry_set_text (label_entry, label);
  dialog = GTK_WIDGET (
    gtk_builder_get_object (builder,
                            "gnunet_conversation_gtk_enter_label_window"));

  /* just pick ANY widget from the main window here... */
  address_entry = GTK_WIDGET (
    GCG_get_main_window_object ("gnunet_conversation_gtk_address_entry"));
  toplevel = gtk_widget_get_toplevel (address_entry);
  if (GTK_IS_WINDOW (toplevel))
    gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));

  gtk_widget_show (dialog);
}


/**
 * User clicked the '> contact' button to move the selected
 * caller's information into our address book.
 *
 * @param button the button
 * @param user_data main loop context (unused)
 */
void
gnunet_conversation_gtk_add_contact_button_clicked_cb (GtkButton *button,
                                                       gpointer *user_data)
{
  GtkEntry *address_entry;

  address_entry = GTK_ENTRY (
    GCG_get_main_window_object ("gnunet_conversation_gtk_address_entry"));
  GSC_get_label_for_name (gtk_entry_get_text (address_entry), "");
}


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