/* Jungle Monkey Search Server
 * Copyright (C) 2000-2001  The Regents of the University of Michigan
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "config.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>

#ifdef JM_ENABLE_GNOME
#include <popt-gnome.h>
#else
#include <popt.h>
#endif

#include "jmintl.h"
#include "util/util.h"

#include "mtp_client.h"
#include "mtp_debug.h"



static void mirrors_func (MtpClient* client, MtpClientStatus status, 
			  GSList* conns, gpointer user_data);
static void mirror_func (MtpClient* client, MtpClientStatus status, 
			 GConn* conn, gpointer user_data);
static void info_func (MtpClient* client, MtpClientStatus status, 
		       gint length, gpointer user_data);
static guint recv_func (MtpClient* client, MtpClientStatus status, 
			const void* buffer, guint length, 
			gpointer user_data);
static void file_func (MtpClient* client, MtpClientStatus status, 
		       gpointer user_data);


/* ******************** */
/* Globals		*/

static int   		verbose = 0;



int main (int argc, char* argv[])
{
  const gchar* url = NULL;
  GURL* gurl;
  GMainLoop* main_loop;

  gboolean get_mirrors = FALSE;
  gboolean get_mirror = FALSE;
  gboolean get_info = FALSE;
  gboolean get_file_from_mirror = FALSE;
  gboolean get_file_from_rendezvous = FALSE;
  gchar*   get_file = NULL;
  MtpClient* client;


  struct poptOption jm_options[] = 
  {
    {"help", 'h', POPT_ARG_NONE, NULL, 1, 
     "Show this help message", NULL},
    {"usage", '\0', POPT_ARG_NONE, NULL, 2, 
     "Display brief usage message", NULL},
    {"version", 0, POPT_ARG_NONE, NULL, 3,
     "Output verson information and exit", NULL},
    {"verbose", 'v', POPT_ARG_NONE, &verbose, 0,
     "Print lots of stuff", NULL},

    {"debug-flags", 'd', POPT_ARG_INT, &mtp_debug_flags, 0, 
     "Set the MTP debug flags", "FLAGS"},

    {"get-mirrors", '\0', POPT_ARG_NONE, &get_mirrors, 0, 
     "Get a list of mirrors from rendezvous", NULL},
    {"get-mirror", '\0', POPT_ARG_NONE, &get_mirror, 0, 
     "Get the best mirror", NULL},
    {"get-info", '\0', POPT_ARG_NONE, &get_info, 0, 
     "Get info from mirror about file", NULL},
    {"get-file-from-mirror", '\0', POPT_ARG_NONE, &get_file_from_mirror, 0, 
     "Request file from mirror", NULL},
    {"get-file-from-rendezvous", '\0', POPT_ARG_NONE, &get_file_from_rendezvous, 0, 
     "Request file via rendezvous", NULL},
    {"get-file", '\0', POPT_ARG_STRING, &get_file, 0, 
     "Request file via rendezvous (get_file function)", NULL},

    {NULL, '\0', 0, NULL, 0, NULL, NULL}
  };

  poptContext ctx;
  int rc;
  int exit_status = EXIT_SUCCESS;


  /* ******************** */
  /* Initialize NLS 	  */
#ifdef ENABLE_NLS
  {
/*      gtk_set_locale(); */
    bindtextdomain (PACKAGE, LOCALEDIR);
    textdomain (PACKAGE);
  }
#endif

  /* ******************** */
  /* Parse command line	  */

  ctx = poptGetContext (NULL, argc, (const char**) argv, jm_options, 0);
  poptSetOtherOptionHelp (ctx, _("[OPTION]... [URL]"));

  while ((rc = poptGetNextOpt(ctx)) > 0)
    {
      switch (rc)
	{
	case 1:	  goto help;	  break;
	case 2:	  goto usage;	  break;
	case 3:   goto version;	  break;
	}
    }

  url = poptGetArg (ctx);

  poptFreeContext (ctx);

  if (!url)
    my_error (_("You must specify a URL.\n"));

  gurl = gnet_url_new (url);
  if (!gurl)
    my_error (_("Malformed URL: %s\n"), url);


  /* ******************** */
  /* Do whatever	  */

  if (get_mirrors)
    {
      client = mtp_client_get_mirrors (gurl, mirrors_func, NULL);
      if (!client)
	g_warning (_("Unable to get mirrors\n"));
    }

  else if (get_mirror)
    {
      client = mtp_client_get_mirror (gurl, mirror_func, NULL);
      if (!client)
	g_warning (_("Unable to get best mirror\n"));
    }

  else if (get_info)
    {
      client = mtp_client_get_info (gurl, info_func, NULL);
      if (!client)
	g_warning (_("Unable to request info\n"));
    }

  else if (get_file_from_mirror)
    {
      client = mtp_client_get_file_mirror (gurl, recv_func, NULL);
      if (!client)
	g_warning (_("Unable to get file from mirror\n"));
    }

  else if (get_file_from_rendezvous)
    {
      client = mtp_client_get_file_rendezvous (gurl, recv_func, NULL);
      if (!client)
	g_warning (_("Unable to get file from rendzvous\n"));
    }

  else if (get_file)
    {
      client = mtp_client_get_file (gurl, get_file, file_func, NULL);
      if (!client)
	g_warning (_("Unable to get file %s\n"), url);
    }


  /* ******************** */
  /* Start the main loop  */

  main_loop = g_main_new (FALSE);
  g_main_run (main_loop);

  exit (EXIT_SUCCESS);

 usage:
  poptPrintUsage (ctx, stdout, 0);
  exit (exit_status);

 help:
  g_print (_("`mtpclient' - MTP Client\n"));
  poptPrintHelp (ctx, stdout, 0);
  g_print (_("\n"
	     "Report bugs to <jm-dev@umich.edu>\n"));
  exit (exit_status);

 version:
  g_print (_("mtpclient %s\n"
	     "Written by David A. Helder\n"
	     "\n"
	     "Copyright (C) 2000-2001 The Regents of the University of Michigan\n"
	     "This is free software; see the source for copying conditions.  There is NO\n"
	     "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
	     VERSION);
  exit (exit_status);
}


static void
mirrors_func (MtpClient* client, MtpClientStatus status, 
	      GSList* conns, gpointer user_data)
{
  int es = EXIT_FAILURE;

  if (status == MTP_CLIENT_STATUS_OK)
    {
      GSList* i;

      g_print (_("Found %d mirrors\n"), g_slist_length (conns));
      
      for (i = conns; i != NULL; i = i->next)
	{
	  GConn* conn;

	  conn = (GConn*) i->data;

	  g_print (_("\t%s:%d\n"), conn->hostname, conn->port);
	  gnet_conn_unref (conn, TRUE);
	}

      es = EXIT_SUCCESS;

    }
  else
    g_warning (_("Failed to get mirrors.\n"));

  mtp_client_delete (client);
  exit (es);
}


static void
mirror_func (MtpClient* client, MtpClientStatus status, 
	     GConn* conn, gpointer user_data)
{
  int es = EXIT_FAILURE;

  if (status == MTP_CLIENT_STATUS_OK)
    {
      g_print (_("Best mirror is %s:%d\n"), conn->hostname, conn->port);
      gnet_conn_unref (conn, TRUE);
      es = EXIT_SUCCESS;
    }
  else
    g_warning (_("Failed to get mirror.\n"));

  mtp_client_delete (client);
  exit (es);
}


static void
info_func (MtpClient* client, MtpClientStatus status, gint length, gpointer user_data)
{
  int es = EXIT_FAILURE;

  if (status == MTP_CLIENT_STATUS_OK)
    {
      g_print (_("Got info: length = %d\n"), length);
      es = EXIT_SUCCESS;
    }
  else
    g_warning (_("Failed to get info.\n"));

  mtp_client_delete (client);
  exit (es);
}


static guint
recv_func (MtpClient* client, MtpClientStatus status, const void* buf, guint len, 
	   gpointer user_data)
{
  if (status == MTP_CLIENT_STATUS_OK)
    {
      if (!buf)
	g_print (_("Transfering file %s (length %d) from %s:%d\n"), 
		 client->url->resource, client->length, 
		 client->conn->hostname, client->conn->port);
      else
	fwrite (buf, len, 1, stdout);

      if (client->length == (client->offset + len))
	{
	  mtp_client_delete (client);
	  g_print ("\nFile transfer completed\n");
	  /* Don't exit: we're mirroring the file now. */
	}
    }
  else
    {
      g_warning (_("Failed to get file.\n"));
      exit (EXIT_FAILURE);
    }

  return len;
}


static void 
file_func (MtpClient* client, MtpClientStatus status, gpointer user_data)
{
  if (status == MTP_CLIENT_STATUS_OK)
    {
      gchar sha[2 * GNET_SHA_HASH_LENGTH + 1];

      gnet_sha_copy_string (client->sha, sha);
      sha[2 * GNET_SHA_HASH_LENGTH] = '\0';

      g_print ("\nFile transfer completed\n");
      g_print ("SHA is %s\n", sha);

      mtp_client_delete (client);
      /* Don't exit: we're mirroring the file now. */
    }
  else if (status == MTP_CLIENT_STATUS_UPDATE)
    {
      g_print ("File transfer update: %d of %d bytes\n", 
	       client->offset, client->length);
    }
  else
    {
      g_warning (_("Failed to get file.\n"));
      mtp_client_delete (client);
      exit (EXIT_FAILURE);
    }
}


syntax highlighted by Code2HTML, v. 0.9.1