/*  gnutrition - a nutrition and diet analysis program.
 *  Copyright( C) 2000, 2001 Edgar Denny (e.denny@ic.ac.uk)
 *
 *  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
 */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <gnome.h>
#include <glade/glade.h>
#include <ctype.h>

#include "food.h"
#include "plan_compute.h"
#include "plan_compute_dlg.h"
#include "nutr_comp_dlg.h"

#define TM_YEAR_BASE 1900

static GladeXML *xml = NULL;
static enum { START_DATE, END_DATE} entry_type;

static void load_xml( void);
static void connect_signals( void);
static void gnutr_popup_calendar( GtkWidget *, GdkWindow *);
static gboolean check_dates( char *, char *);

/* callbacks. */
static void on_cancel_button_released( GtkButton *, gpointer);
static void on_compute_button_released( GtkButton *, gpointer);
static void on_cal_start_button_released( GtkButton *, gpointer);
static void on_cal_end_button_released( GtkButton *, gpointer);
static void on_day_selected( GtkCalendar *, gpointer);

/* load the glade xml if not already loaded. */
static void
load_xml( )
{
	static gboolean loaded_xml = FALSE;

	/* load the glade interface. */
	if ( !loaded_xml) {
		xml = glade_xml_new( 
			GNUTRITION_GLADEDIR "/plan_compute_dlg.glade", NULL);
		loaded_xml = TRUE;
		if ( xml) {
			connect_signals( );
		} else {
			g_log( "Gnutrition", G_LOG_LEVEL_ERROR,
				"cannot load: plan_compute_dlg.glade\n");
			return;
		}
	}
}

static void
connect_signals( )
{
	gtk_signal_connect( GTK_OBJECT( 
		glade_xml_get_widget( xml, "cancel_button")), "released", 
		GTK_SIGNAL_FUNC( on_cancel_button_released), NULL);

	gtk_signal_connect( GTK_OBJECT( 
		glade_xml_get_widget( xml, "compute_button")), "released", 
		GTK_SIGNAL_FUNC( on_compute_button_released), NULL);
	
	gtk_signal_connect( GTK_OBJECT( 
		glade_xml_get_widget( xml, "cal_start_button")), "released", 
		GTK_SIGNAL_FUNC( on_cal_start_button_released), NULL);

	gtk_signal_connect( GTK_OBJECT( 
		glade_xml_get_widget( xml, "cal_end_button")), "released", 
		GTK_SIGNAL_FUNC( on_cal_end_button_released), NULL);
	
	gtk_signal_connect( GTK_OBJECT(
		glade_xml_get_widget( xml, "calendar")), "day_selected",
		GTK_SIGNAL_FUNC( on_day_selected), NULL);
}

/* Display the compute plan nutrient total dialog. */
void
gnutr_show_plan_compute_dlg()
{
	GtkWidget *dlg;
	if ( !xml) load_xml();

	dlg = glade_xml_get_widget( xml, "plan_compute_dlg");
	gtk_widget_show( dlg);
}

/* When the "Cancel" button is released. Hide the dialog. */
static void
on_cancel_button_released( GtkButton *button,
                          gpointer   user_data)
{
	GtkWidget *dlg;

	dlg = glade_xml_get_widget( xml, "plan_compute_dlg");
	gtk_widget_hide( dlg);
}

/* compare the two dates. If date1 > date2 return TRUE,
 * else return FALSE. */
static gboolean
check_dates( char *date1, char *date2)
{
	char **split_date1, **split_date2;

	split_date1 = g_strsplit( date1, "-", 3);
	split_date2 = g_strsplit( date2, "-", 3);

	/* the year. */
	if ( atoi(split_date1[0]) > atoi( split_date2[0])) {
		g_strfreev( split_date1);
		g_strfreev( split_date2);
		return TRUE;
	}

	/* the month. */
	if ( atoi(split_date1[1]) > atoi( split_date2[1])) {
		g_strfreev( split_date1);
		g_strfreev( split_date2);
		return TRUE;
	}

	/* the day. */
	if ( atoi(split_date1[2]) > atoi( split_date2[2])) {
		g_strfreev( split_date1);
		g_strfreev( split_date2);
		return TRUE;
	}
	return FALSE;
}

/* When the "Compute" button is released. */
static void
on_compute_button_released( GtkButton *button,
                            gpointer   user_data)
{
	GtkWidget *dlg;
	GtkWidget *radio_button;
	gboolean avg_active;
	GtkWidget *start_entry, *end_entry;
	char *start_date = NULL, *end_date = NULL;
	GList *list_nutr;

	start_entry = glade_xml_get_widget( xml, "start_entry");
	end_entry = glade_xml_get_widget( xml, "end_entry");
	start_date = gtk_entry_get_text( GTK_ENTRY( start_entry));
	end_date = gtk_entry_get_text( GTK_ENTRY( end_entry));

	/* check that both a start date and end date are given, and
	 * that the end date is identical to, or later than, the
	 * start date. */
	if ( strlen(start_date) == 0) {
		GtkWidget *warn_msg;
		warn_msg = gnome_warning_dialog( "No start date is given.");
		gtk_widget_show (warn_msg);
		return;
	}
	if ( strlen(end_date) == 0) {
		GtkWidget *warn_msg;
		warn_msg = gnome_warning_dialog( "No end date is given.");
		gtk_widget_show (warn_msg);
		return;
	}
	if ( check_dates( start_date, end_date)) {
		GtkWidget *warn_msg;
		char *text;
		text = g_strdup( "The start date is later\nthe end date.");
		warn_msg = gnome_warning_dialog( text);
		gtk_widget_show (warn_msg);
		g_free( text);
		return;
	}

	radio_button = glade_xml_get_widget( xml, "avg_radio");
	avg_active = GTK_TOGGLE_BUTTON( radio_button)->active;

	/* compute the nutrient plan nutrient total between the two
	 * dates. */
	list_nutr = gnutr_compute_plan_nutr_comp( start_date, end_date,
			avg_active);

	gnutr_show_nutr_comp_dlg( list_nutr, 1);

	dlg = glade_xml_get_widget( xml, "plan_compute_dlg");
	gtk_widget_hide( dlg);
}

/* callback when a day is selected from the calendar. */
static void
on_day_selected( GtkCalendar *calender,
                 gpointer     user_data)
{
	struct tm tm;
	time_t time;
	GtkWidget *calendar = glade_xml_get_widget( xml, "calendar");
	GtkWidget *date_entry;
	static char buff[150];
	enum { START_DATE, END_DATE};

	memset( &tm, 0, sizeof( tm));
	gtk_calendar_get_date( GTK_CALENDAR( calendar), &tm.tm_year,
			&tm.tm_mon, &tm.tm_mday);
	tm.tm_year -= TM_YEAR_BASE;
	time = mktime( &tm);

	strftime( buff, 149, "%Y-%m-%d", gmtime(&time));

	if ( entry_type == START_DATE) {
		date_entry = glade_xml_get_widget( xml, "start_entry");
	} else {
		date_entry = glade_xml_get_widget( xml, "end_entry");
	}
	gtk_entry_set_text( GTK_ENTRY( date_entry), buff);
}

/* show the calendar popup window. */
static void
gnutr_popup_calendar( GtkWidget *button,
                      GdkWindow *button_parent)
{
	GtkWidget *calendar_popup_win = glade_xml_get_widget( xml, "cal_win");

	g_return_if_fail( button);
	g_return_if_fail( button_parent);

	if ( !GTK_WIDGET_VISIBLE( calendar_popup_win)) {
		int x1, y1, x2, y2, w2, h2, w3, x3, y3;

		/* get position of of top left coords of dialog window. */ 
		gdk_window_get_origin( button_parent, &x1, &y1);

		/* get the coords of the button w.r.t. its parent. */
		x2 = button->allocation.x;
		y2 = button->allocation.y;

		w2 = button->allocation.width;
		h2 = button->allocation.height;

		/* we need to know the width of the popup window, so it must
		 * be realized first. */
		if ( !GTK_WIDGET_REALIZED( calendar_popup_win)) {
			gtk_widget_realize( calendar_popup_win);
		}
		w3 = calendar_popup_win->allocation.width;

		/* set the position of the calendar popup window. */
		x3 = x1 + x2 + w2 - w3;
		y3 = y1 + y2 + h2;
		gtk_widget_set_uposition( calendar_popup_win, x3, y3);

		gtk_widget_show( calendar_popup_win);
	} else {
		gtk_widget_hide( calendar_popup_win);
	}
}

/* when the "Calendar" button for starting date is released. */
static void
on_cal_start_button_released( GtkButton *button,
                              gpointer user_data)
{
	GtkWidget *cal_button;
	GdkWindow *parent;

	cal_button = glade_xml_get_widget( xml, "cal_start_button");
	parent = gtk_widget_get_parent_window( cal_button);
	gnutr_popup_calendar( cal_button, parent);

	entry_type = START_DATE;
}

/* when the "Calendar" button for ending date is released. */
static void
on_cal_end_button_released( GtkButton *button,
                            gpointer user_data)
{
	GtkWidget *cal_button;
	GdkWindow *parent;

	cal_button = glade_xml_get_widget( xml, "cal_end_button");
	parent = gtk_widget_get_parent_window( cal_button);
	gnutr_popup_calendar( cal_button, parent);

	entry_type = END_DATE;
}
