/* OpenVAS-Client
 * $Id$
 * Description: The standard error/warning/info dialogs of OpenVAS-Client.
 *
 * Author(s):
 * Thomas Arendsen Hein <thomas@intevation.de>
 * Jan-Oliver Wagner <jan@intevation.de>
 *
 * Copyright:
 * Copyright (C) 2004 Intevation GmbH
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2,
 * or, at your option, any later version as published by the Free
 * Software Foundation
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * In addition, as a special exception, you have
 * permission to link the code of this program with the OpenSSL
 * library (or with modified versions of OpenSSL that use the same
 * license as OpenSSL), and distribute linked combinations including
 * the two. You must obey the GNU General Public License in all
 * respects for all of the code used other than OpenSSL. If you
 * modify this file, you may extend this exception to your version
 * of the file, but you are not obligated to do so. If you do not
 * wish to do so, delete this exception statement from your version.
 */

#include <time.h>
#include <includes.h>
#include <stdarg.h>

#include "globals.h"
#include "error_dlg.h"
#include "nessus_i18n.h"

#ifdef USE_GTK
#include <gtk/gtk.h>
#endif

#define DIALOG_TYPE_INFO 0
#define DIALOG_TYPE_WARNING 1
#define DIALOG_TYPE_ERROR 2

#define DIALOG_NORMAL 0
#define DIALOG_AND_WAIT 1


void
show_dialog_std(type, wait, fmt, ap)
  int type;
  int wait;
  char *fmt;
  va_list ap;
{
  fprintf(stderr, "*** ");
  switch(type)
  {
    case DIALOG_TYPE_INFO:
      fprintf(stderr, _("Info: "));
      break;
    case DIALOG_TYPE_WARNING:
      fprintf(stderr, _("Warning: "));
      break;
    default: /* DIALOG_TYPE_ERROR  or other */
      fprintf(stderr, _("Error: "));
  }
  vfprintf(stderr, fmt, ap);
  fprintf(stderr, "\n");
  if(wait == DIALOG_AND_WAIT)
  {
    fprintf(stderr, _("Press <Enter> to continue ...\n"));
    getchar(); /* RATS: ignore, not reading into any buffer */
  }
}


#ifdef USE_GTK
void
show_dialog_gtk_close(dialog, response_id, dialog_running)
  GtkDialog *dialog;
  gint response_id;
  gboolean *dialog_running;
{
  gtk_widget_destroy(GTK_WIDGET(dialog));
  *dialog_running = FALSE;
}

void
show_dialog_gtk_popup(type, wait, error_text)
  int type;
  int wait;
  char *error_text;
{
  void *context_window = arg_get_value(MainDialog, "CONTEXT");
  GtkWindow *window;
  GtkWidget *dialog;
  int messagetype;
  static gboolean dialog_running = FALSE;

  while(dialog_running)
    gtk_main_iteration_do(TRUE);

  if(context_window)
    window = GTK_WINDOW(context_window);
  else
  {
    window = NULL;
    wait = DIALOG_AND_WAIT;
  }

  /*
   * XXX
   * Always wait. This can be removed if other windows are created
   * using a common function which sets "dialog_running", too.
   */
  wait = DIALOG_AND_WAIT;

  switch(type)
  {
    case DIALOG_TYPE_INFO:
      messagetype = GTK_MESSAGE_INFO;
      break;
    case DIALOG_TYPE_WARNING:
      messagetype = GTK_MESSAGE_WARNING;
      break;
    default: /* DIALOG_TYPE_ERROR  or other */
      messagetype = GTK_MESSAGE_ERROR;
  }

  /* create the user dialog */
  dialog = gtk_message_dialog_new(window, 0, messagetype,
      wait == DIALOG_AND_WAIT ? GTK_BUTTONS_OK : GTK_BUTTONS_CLOSE,
      "%s", error_text);

  if(wait == DIALOG_AND_WAIT)
  {
    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
  }
  else
  {
    dialog_running = TRUE;
    gtk_widget_show(dialog);
    g_signal_connect(dialog, "response",
	G_CALLBACK(show_dialog_gtk_close),
	&dialog_running);
  }
}

void
show_dialog_gtk_log(type, error_text)
  int type;
  char *error_text;
{
  GtkWidget *textview = arg_get_value(MainDialog, "MSGLOGTEXT");
  GtkWidget *scrolledwin = arg_get_value(MainDialog, "MSGLOGSCROLL");
  GtkTextBuffer *log;
  GtkTextIter iter;
  GtkAdjustment *vadjust;
  char *msgtype;
  struct tm* localtime_;
  time_t time_;
  gchar* time_type;
  gchar* time_newlineless; // Will contain e.g. 04:12:12

  time_ = time(NULL);
  localtime_ = localtime(&time_);

  if(!textview || !scrolledwin)
    return;

  switch(type)
  {
    case DIALOG_TYPE_INFO:
      msgtype = _("Info: ");
      break;
    case DIALOG_TYPE_WARNING:
      msgtype = _("Warning: ");
      break;
    default: /* DIALOG_TYPE_ERROR  or other */
      msgtype = _("Error: ");
  }

  time_newlineless = g_strdup (asctime(localtime_));
  // Strip the newline
  time_newlineless[strlen(time_newlineless)-1] = '\0';
  time_type = g_strdup_printf("[%s] %s", time_newlineless, msgtype);


  /* Submit the message to the log text view. */
  log = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
  gtk_text_buffer_get_end_iter(log, &iter);
  gtk_text_buffer_insert(log, &iter, time_type, -1);
  gtk_text_buffer_get_end_iter(log, &iter);
  gtk_text_buffer_insert(log, &iter, error_text, -1);

  gtk_text_buffer_get_end_iter(log, &iter);
  gtk_text_buffer_insert(log, &iter, "\n", -1);

  vadjust = gtk_scrolled_window_get_vadjustment(
      GTK_SCROLLED_WINDOW(scrolledwin));
  gtk_adjustment_set_value(vadjust, vadjust->upper - 1);

  g_free (time_newlineless);
  g_free (time_type);
}

void
show_dialog_gtk(type, wait, fmt, ap)
  int type;
  int wait;
  char *fmt;
  va_list ap;
{
  char *error_text = g_strdup_vprintf(fmt, ap);

  show_dialog_gtk_log(type, error_text);
  show_dialog_gtk_popup(type, wait, error_text);
  g_free(error_text);
}
#endif


void
show_dialog(type, wait, fmt, ap)
  int type;
  int wait;
  char *fmt;
  va_list ap;
{
#ifdef USE_GTK
  if(!F_quiet_mode)
    show_dialog_gtk(type, wait, fmt, ap);
  else
#endif /* USE_GTK */
    show_dialog_std(type, wait, fmt, ap);
}

/*
 * functions called by the application
 */

/**
 * _The_ function to be used to display an error message, both with or without
 * gui.
 * Arguments in printf fashion.
 * @param fmt Formatting string, optionally followed by values, (printf-like).
 */
void
show_error(char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  show_dialog(DIALOG_TYPE_ERROR, DIALOG_NORMAL, fmt, ap);
  va_end(ap);
}

void
show_warning(char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  show_dialog(DIALOG_TYPE_WARNING, DIALOG_NORMAL, fmt, ap);
  va_end(ap);
}

void
show_info(char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  show_dialog(DIALOG_TYPE_INFO, DIALOG_NORMAL, fmt, ap);
  va_end(ap);
}


void
show_error_and_wait(char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  show_dialog(DIALOG_TYPE_ERROR, DIALOG_AND_WAIT, fmt, ap);
  va_end(ap);
}

void
show_warning_and_wait(char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  show_dialog(DIALOG_TYPE_WARNING, DIALOG_AND_WAIT, fmt, ap);
  va_end(ap);
}

void
show_info_and_wait(char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  show_dialog(DIALOG_TYPE_INFO, DIALOG_AND_WAIT, fmt, ap);
  va_end(ap);
}
