/***************************************************************************
                                reconnect-dialog.c
                                ------------------
    begin                : Sat Oct 11 2003
    copyright            : (C) 2003 by Tim-Philipp Müller
    email                : t.i.m at orange dot net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "core-conn.h"
#include "global.h"
#include "misc_gtk.h"
#include "misc_strings.h"
#include "reconnect-dialog.h"
#include "status_page.h"

#include <gtk/gtklabel.h>
#include <gtk/gtkmain.h>
#include <gtk/gtkwindow.h>
#include <gtk/gtkhbox.h>
#include <gtk/gtkvbox.h>
#include <gtk/gtkprogressbar.h>
#include <gtk/gtkdialog.h>


#define RC_WAIT_SECONDS   15             /* The number of seconds until we try to reconnect */

/* variables */

static guint              pulse_counter; /* 0 */ /* how many times have we pulsed the progress bar? */

static guint              timer_handle;  /* 0 */

static GtkWidget         *rcdialog;      /* NULL */

static GtkWidget         *pbar;          /* NULL */


/* functions */

static void               rcdialog_show       (GtkWidget *mainwindow);

static void               rcdialog_hide       (void);

static void               onReconnectNow      (GtkWidget *nowbutton, gpointer data);

static void               onStopReconnecting  (GtkWidget *stopbutton, gpointer data);

static gboolean           onPulseTimeout      (gpointer data);

static void               atExit              (void);

static void               onCoreConnStatus (GuiCoreConn *conn, guint status, GtkWidget *mainwindow);


/******************************************************************************
 *
 *   rcdialog_show
 *
 ******************************************************************************/

static void
rcdialog_show (GtkWidget *mainwindow)
{
	g_assert ((rcdialog) && GTK_IS_DIALOG(rcdialog));

	gtk_grab_add(rcdialog);
	gtk_window_set_transient_for(GTK_WINDOW(rcdialog), GTK_WINDOW(mainwindow));
	gtk_widget_show(rcdialog);

	if (timer_handle == 0)
		timer_handle = g_timeout_add (500, onPulseTimeout, NULL);

	pulse_counter = 0;
}

/******************************************************************************
 *
 *   rcdialog_hide
 *
 ******************************************************************************/

static void
rcdialog_hide (void)
{
	g_assert ((rcdialog) && GTK_IS_DIALOG(rcdialog));

	gtk_grab_remove (rcdialog);
	gtk_window_set_transient_for(GTK_WINDOW(rcdialog), NULL);
	gtk_widget_hide (rcdialog);

	if (timer_handle > 0)
	{
		g_source_remove(timer_handle);
		timer_handle = 0;
	}

	pulse_counter = 0;
}

/******************************************************************************
 *
 *   onReconnectNow
 *
 *   If the connect attempt is succesful, we don't
 *     need another dialog ('reconnect' or 'connect to'),
 *     and the connection callback will destroy the
 *     existing one for us.
 *
 *   If the connect fails, the destroy handler will
 *     bring up a new dialog.
 *
 ******************************************************************************/

static void
onReconnectNow (GtkWidget *nowbutton, gpointer data)
{
	status_msg (_("GUI: Trying to reconnect to core ...\n"));

	if (gui_core_conn_reconnect(core))
	{
		rcdialog_hide();
	}
	else
	{
		status_msg (_("GUI: Reconnect not possible for some reason (bug!) ...\n"));
	}
}



/******************************************************************************
 *
 *  onStopReconnecting
 *
 ******************************************************************************/

static void
onStopReconnecting (GtkWidget *stopbutton, gpointer data)
{
	if (timer_handle > 0)
		g_source_remove(timer_handle);

	timer_handle      = 0;
	pulse_counter     = 0;

	gtk_grab_remove (GTK_WIDGET(rcdialog));
	gtk_widget_hide (GTK_WIDGET(rcdialog));

	/* will emit CLOSED_DELIBERATELY conn status
	 *  signal, which in turn will bring up the
	 *  'proper' connect-to dialog */
	gui_core_conn_disconnect(core);
}


/******************************************************************************
 *
 *  onPulseTimeout
 *
 ******************************************************************************/

static gboolean
onPulseTimeout (gpointer data)
{
	guint	counter = ++pulse_counter;

	if (gui_core_conn_is_alive(core))
	{
		timer_handle = 0;
		return FALSE;
	}

	gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(pbar), (counter%(RC_WAIT_SECONDS*2))*1.0/30.0);

	if (counter%(RC_WAIT_SECONDS*2) > 0)
		return TRUE;	/* call us again */

	timer_handle = 0;

	onReconnectNow (NULL, NULL);

	return FALSE;	/* don't call us again */
}


/******************************************************************************
 *
 *  onDeleteEvent
 *
 ******************************************************************************/

static gint
onDeleteEvent (GtkWidget *rcdialog, GdkEvent *event, gpointer data)
{
	rcdialog_hide();

	/* will emit CLOSED_DELIBERATELY conn status
	 *  signal, which in turn will bring up the
	 *  'proper' connect-to dialog */
	gui_core_conn_disconnect(core);

	return TRUE; /* do not destroy */
}


/******************************************************************************
 *
 *  atExit
 *
 ******************************************************************************/

static void
atExit (void)
{
	gtk_widget_destroy(rcdialog);
	rcdialog = NULL;
}


/******************************************************************************
 *
 *  onCoreConnStatus
 *
 ******************************************************************************/

static void
onCoreConnStatus (GuiCoreConn *conn, guint status, GtkWidget *mainwindow)
{
	static guint    commcounter; /* 0 */  /* how often we had status 'communicating' */
	static guint    laststatus;

	switch (status)
	{
		case CONN_STATUS_CLOSED_TIMEOUT:
		case CONN_STATUS_CLOSED_TIMEOUT_NO_DATA:
		case CONN_STATUS_CLOSED_UNEXPECTEDLY:
		{
			/* only try to reconnect if we have already
			 *  been connected to the core once before */
			if (commcounter > 0)
			{
				rcdialog_show(mainwindow);
			}
		}
		break;

		case CONN_STATUS_COMMUNICATING:
		{
			++commcounter;
		}
		/* no break! */

		default:
		{
			rcdialog_hide();
		}
		break;
	}

	laststatus = status;
}


/******************************************************************************
 *
 *  reconnect_dialog_create
 *
 ******************************************************************************/

void
reconnect_dialog_create (GtkWidget *mainwindow)
{
	const gchar *labeltxt;
	GtkWidget   *rclabel;
	GtkWidget   *cnow_button;
	GtkWidget   *stop_button;
	GtkWidget   *buttonvbox;

	rcdialog = gtk_dialog_new();

	gtk_window_set_title (GTK_WINDOW (rcdialog), _("Re-connecting to core ..."));
	gtk_window_set_position (GTK_WINDOW(rcdialog), GTK_WIN_POS_CENTER_ALWAYS);

	buttonvbox = GTK_DIALOG(rcdialog)->action_area;

	new_button_pack_and_signal_connect (&cnow_button, buttonvbox, _(" Reconnect now "), onReconnectNow, NULL, 1);

	new_button_pack_and_signal_connect (&stop_button, buttonvbox, _(" Stop "), onStopReconnecting, NULL, 1);

	g_signal_connect (rcdialog, "delete-event", G_CALLBACK(onDeleteEvent),  NULL);

	labeltxt = UTF8_SHORT_PRINTF("%s",  _("\nThe connection to the core broke unexpectedly\n"
	                                      "or auto-connect on start-up failed.\n\n"
	                                      "  I will try to reconnect to the core in a couple of seconds...  "));

	rclabel = gtk_label_new(labeltxt);
	gtk_box_pack_start (GTK_BOX(GTK_DIALOG(rcdialog)->vbox),rclabel,FALSE,TRUE,0);
	gtk_widget_show (rclabel);

	pbar = gtk_progress_bar_new();
	gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR(pbar), GTK_PROGRESS_LEFT_TO_RIGHT);
	gtk_box_pack_start (GTK_BOX (GTK_DIALOG(rcdialog)->vbox), pbar, TRUE, TRUE, 20);
	gtk_widget_show (pbar);

	g_atexit(&atExit);

	g_signal_connect(core, "core-conn-status", (GCallback) onCoreConnStatus, mainwindow);
}



