/*
     This file is part of GNUnet.
     Copyright (C) 2012 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/setup/gnunet-setup-hostlist-server.c
 * @brief (de)sensitize UI elements related to hostlist server configuration
 *        based on the build configuration of the hostlist daemon
 * @author Christian Grothoff
 */
#include "gnunet-setup.h"
#include <gnunet/gnunet_util_lib.h>


/**
 * Timeout for hostlist daemon to print help information
 */
#define CMD_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)


/**
 * Function called to report the result of testing the hostlist daemon.
 *
 * @param cls closure
 * @param result GNUNET_YES if the hostlist daemon has an integrated hostlist
 *               server, GNUNET_NO otherwise
 */
typedef void (*TestHostlistDaemonCallback) (void *cls, int result);


/**
 * Context for running hostlist daemon and processing its output.
 */
struct CommandContext
{
  /**
   * Handle to the command.
   */
  struct GNUNET_OS_CommandHandle *cmd;

  /**
   * Where to pass the result.
   */
  TestHostlistDaemonCallback callback;

  /**
   * Closure for the callback.
   */
  void *callback_cls;

  /**
   * GNUNET_YES if the target argument was found, GNUNET_NO otherwise.
   */
  int found;
};


static void
set_checkbutton_status (void *cls, int result)
{
  GtkWidget *widget = cls;
  GtkToggleButton *button;

  if (GNUNET_YES != result)
  {
    gtk_widget_set_sensitive (widget, FALSE);
    button = GTK_TOGGLE_BUTTON (widget);
    if (button == NULL)
    {
      GNUNET_break (0);
      return;
    }
    /* also deactivate the checkbutton since this option could be enabled
       by editing the config file manually */
    gtk_toggle_button_set_active (button, FALSE);
  }
}


static void
set_spinbutton_status (void *cls, int result)
{
  GtkWidget *widget = cls;

  if (GNUNET_YES != result)
    gtk_widget_set_sensitive (widget, FALSE);
}


/**
 * Process the output from the 'gnunet-daemon-hostlist -h' command
 * to find out whether the hostlist daemon can provide a hostlist server.
 *
 * @param cls the 'struct CommandContext'
 * @param line line of output, NULL at the end
 */
static void
process_hostlist_daemon_output (void *cls, const char *line)
{
  struct CommandContext *ctx = cls;
  char *t;
  char *w;

  if (NULL == line)
  {
    ctx->callback (ctx->callback_cls, ctx->found);
    GNUNET_OS_command_stop (ctx->cmd);
    GNUNET_free (ctx);
    return;
  }

  t = GNUNET_strdup (line);
  w = strtok (t, " ");
  while (w != NULL)
  {
    if (0 == strcmp (w, "--provide-hostlist"))
    {
      ctx->found = GNUNET_YES;
      break;
    }
    w = strtok (NULL, " ");
  }
  GNUNET_free (t);
}


/**
 * Run 'gnunet-daemon-hostlist -h'. Output of this command will let us
 * know whether the hostlist daemon can provide a hostlist server.
 *
 * @param callback function to call with the result
 * @param cls closure for the callback
 */
static void
test_hostlist_daemon (TestHostlistDaemonCallback callback, void *cls)
{
  struct CommandContext *ctx;
  char *binary;

  ctx = GNUNET_new (struct CommandContext);
  ctx->callback = callback;
  ctx->callback_cls = cls;
  ctx->found = GNUNET_NO;
  binary = GNUNET_OS_get_libexec_binary_path ("gnunet-daemon-hostlist");
  ctx->cmd = GNUNET_OS_command_run (&process_hostlist_daemon_output,
                                    ctx,
                                    CMD_TIMEOUT,
                                    binary,
                                    "gnunet-daemon-hostlist",
                                    "-h",
                                    NULL);
  GNUNET_free (binary);
  if (NULL == ctx->cmd)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _ ("Could not determine whether the hostlist daemon has"
                   " an integrated hostlist server!\n"));
    GNUNET_free (ctx);
  }
}


void
GNUNET_setup_hostlist_offer_hostlist_checkbutton_realize_cb (GtkWidget *widget,
                                                             gpointer user_data)
{
  test_hostlist_daemon (&set_checkbutton_status, widget);
}


void
GNUNET_setup_hostlist_advertise_checkbutton_realize_cb (GtkWidget *widget,
                                                        gpointer user_data)
{
  test_hostlist_daemon (&set_checkbutton_status, widget);
}


void
GNUNET_setup_hostlist_server_port_spin_button_realize_cb (GtkWidget *widget,
                                                          gpointer user_data)
{
  test_hostlist_daemon (&set_spinbutton_status, widget);
}


/* end of gnunet-setup-hostlist-server.c */
