/*  gnutrition - a nutrition and diet analysis program.
 *  Copyright (C) 2000 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 "text_util.h"
#include "food.h"
#include "recipe.h"
#include "load_data.h"
#include "nutrgoal_io.h"
#include "recipe_win.h"
#include "support.h"
#include "nutr_goal_dlg.h"
#include "nutr_comp_dlg.h"
#include "food_srch_dlg.h"
#include "recipe_file_dlg.h"
#include "edit_food_dlg.h"
#include "messages.h"

static GladeXML *xml = NULL;
static void load_xml( void);
static Recipe_t *recipe = NULL;

/* 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 "/recipe_win.glade", 
				NULL);
		loaded_xml = TRUE;

		if (  xml != NULL)
		{
			glade_xml_signal_autoconnect( xml);
		}
		else
		{
			g_log( "Gnutrition", G_LOG_LEVEL_ERROR,
					"cannot load glade file: recipe_win.glade\n");
			return;
		}
	}
}

/* show the recipe window. */
void
gnutr_show_recipe_win()
{
	if ( xml == NULL) load_xml();

	recipe = ( Recipe_t *)g_malloc( sizeof( Recipe_t));

	recipe->nutr = ( Nutrition_t *)g_malloc( sizeof( Nutrition_t));
	recipe->ingredient_clist = (GtkCList *) 
			glade_xml_get_widget( xml, "recipe_win_ingredient_clist");
	recipe->no_ingredients = 0;
	recipe->file_name = NULL;
	recipe->selected_row = -1;
	recipe->name = NULL;

	/* read in nutrient goals. */
	gnutr_read_nutr_goal( &(recipe->nutr));

	gtk_widget_show( glade_xml_get_widget( xml, "recipe_win"));
}

/* Open the file dialog when "open" is selected from the recipe
 * window menu item. */
void
on_recipe_win_open_activate( GtkMenuItem *menuitem,
                             gpointer     user_data)
{
	gnutr_show_file_open_dlg();
}

/* Exit the application when "exit" is selected from the recipe
 * window menu bar. */
void
on_recipe_win_exit_activate( GtkMenuItem *menuitem,
                             gpointer     user_data)
{
	GList *food_glist = gnutr_ret_food_glist();
	gnutr_free_recipe();
	gnutr_free_food_glist( &food_glist);
	gtk_main_quit();
}

/* Show the food selection/search dialog. */
void
on_recipe_win_add_button_released( GtkButton *button,
                                   gpointer   user_data)
{
	gnutr_show_srch_dlg();
}

/* reopens the search dialog window, so an ingredient can be edited,
 * when the edit button is released in the AppBar on the recipe window. */
void
on_recipe_win_edit_button_released( GtkButton *button,
                                    gpointer   user_data)
{
	if ( recipe->selected_row == -1)
	{
		gnutr_show_msg_no_ingredient_selected();
	}
	else
	{
		gnutr_show_edit_food_dlg();
/*		recipe->selected_row = -1; */
	}
}

/* Open a file dialog when "new recipe" is selected from the
 * recipe window menu bar. */
void
on_recipe_win_new_file_activate( GtkMenuItem *menuitem,
                                 gpointer     user_data)
{
	GtkButton *dummy = NULL;
	on_recipe_win_new_button_released( dummy, user_data);
}

/* Open the search dialog when "add food" is selected from the
 * recipe window menu bar. */
void
on_recipe_win_add_food_activate( GtkMenuItem *menuitem,
                                 gpointer     user_data)
{
	GtkButton *dummy = NULL;
	on_recipe_win_add_button_released( dummy, user_data);
}

/* Open the search dialog when "edit food" is selected from the
 * recipe window menu bar. */
void
on_recipe_win_edit_food_activate( GtkMenuItem *menuitem,
                                  gpointer     user_data)
{
	GtkButton *dummy = NULL;
	on_recipe_win_edit_button_released( dummy, user_data);
}

/* Delete the selected ingredient when "delete food" is selected from the
 * recipe window menu bar. */
void
on_recipe_win_delete_food_activate( GtkMenuItem *menuitem,
                                    gpointer     user_data)
{
	GtkButton *dummy = NULL;
	on_recipe_win_delete_button_released( dummy, user_data);
}

/* Open the nutrient goal dialog when "nutrient goal" is selected from the
 * recipe window menu bar. */
void
on_recipe_win_pref_activate( GtkMenuItem *menuitem,
                             gpointer     user_data)
{
	gnutr_show_nutr_goal_dlg();
}

/* The about dialog. */
void
on_recipe_win_about_activate( GtkMenuItem *menuitem,
                              gpointer     user_data)
{
	GtkWidget *about_dlg = glade_xml_get_widget( xml, "gnutrition_about");
	gnome_dialog_close_hides( GNOME_DIALOG( about_dlg), TRUE);
	gtk_widget_show( about_dlg); 
}

/* When the "Open" button is released on the AppBar of the recipe window. */
void
on_recipe_win_open_button_released( GtkButton *button,
                                    gpointer   user_data)
{
	gnutr_show_file_open_dlg();
}

/* removes an ingredient from the recipe when the delete button is
 * released in the AppBar on the recipe window. */
void
on_recipe_win_delete_button_released( GtkButton *button,
                                      gpointer   user_data)
{
	/* check that an ingredient has been selected. */
	if ( recipe->selected_row == -1)
	{
		gnutr_show_msg_no_ingredient_selected();
	}
	else
	{
		gtk_clist_remove( recipe->ingredient_clist, recipe->selected_row);
		recipe->no_ingredients--;
		recipe->selected_row = -1;
	}
}

/* get the row that has been selected the the ingredient list. */
void
on_recipe_win_ingredient_clist_select_row( GtkCList *clist,
                                           gint      row,
                                           gint      column,
                                           GdkEvent *event,
                                           gpointer  user_data)
{
	recipe->selected_row = row;
}


/* Just here for the future. */
void
on_recipe_win_manual_activate( GtkMenuItem *menuitem,
                               gpointer     user_data)
{

}

/* reset all the recipe text entries to null and free
 * any existing memory. */
void
gnutr_free_recipe()
{		
	GtkWidget *recipe_name_entry = 
			glade_xml_get_widget( xml, "recipe_win_recipe_name_entry");
	GtkWidget *no_serv_entry = 
			glade_xml_get_widget( xml, "recipe_win_no_serv_entry");

	recipe->ingredient_clist = (GtkCList *)
			glade_xml_get_widget( xml, "recipe_win_ingredient_clist");

	gtk_clist_clear( recipe->ingredient_clist);

	recipe->no_ingredients = 0;

	g_free( recipe->file_name); 
	recipe->file_name = NULL;

	recipe->name = NULL;
	gtk_entry_set_text( GTK_ENTRY( recipe_name_entry), "");

	recipe->no_serv = NULL;
	gtk_entry_set_text( GTK_ENTRY( no_serv_entry), "");
}

/* update the status bar on entering the new recipe button in the 
 * recipe window. */
void
on_recipe_win_new_button_enter( GtkButton *button,
                                 gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_push( GNOME_APPBAR( widget), 
			"Create a New Recipe.");
}

/* update the status bar on entering the open recipe file button in the 
 * recipe window. */
void
on_recipe_win_open_button_enter( GtkButton *button,
                                 gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_push( GNOME_APPBAR( widget), 
			"Open an Existing Recipe File.");
}

/* update the status bar on entering the save recipe to file button in the 
 * recipe window. */
void
on_recipe_win_save_button_enter( GtkButton *button,
                                 gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_push( GNOME_APPBAR( widget), 
			"Save the Recipe to File.");
}

/* update the status bar on entering the add ingredient to recipe button
 * in the recipe window. */
void
on_recipe_win_add_button_enter( GtkButton *button,
                                gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_push( GNOME_APPBAR( widget), 
			"Add an Ingredient to the Recipe.");
}

/* update the status bar on entering the delete ingredient from recipe 
 * button in the recipe window. */
void
on_recipe_win_delete_button_enter( GtkButton *button,
                                   gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_push( GNOME_APPBAR( widget), 
			"Delete the Selected Ingredient from the Recipe.");
}

/* update the status bar on entering the edit ingredient 
 * button in the recipe window. */
void
on_recipe_win_edit_button_enter( GtkButton *button,
                                 gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_push( GNOME_APPBAR( widget), 
			"Edit the Selected Ingredient.");
}

/* update the status bar on entering the show nutrient composition dialog
 * button in the recipe window. */
void
on_recipe_win_nutr_comp_button_enter( GtkButton *button,
                                      gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_push( GNOME_APPBAR( widget), 
			"Open the Recipe Nutrient Composition Dialog.");
}

/* update the status bar on entering the show nutrient goal dialog
 * button in the recipe window. */
void
on_recipe_win_nutr_goal_button_enter( GtkButton *button,
                                      gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_push( GNOME_APPBAR( widget), 
			"Open the Nutrient Goal Dialog.");
}

/* on pointer leaving new recipe button in recipe window. */
void
on_recipe_win_new_button_leave( GtkButton *button,
                                gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_clear_stack( GNOME_APPBAR( widget));
}

/* on pointer leaving open recipe button in recipe window. */
void
on_recipe_win_open_button_leave( GtkButton *button,
                                 gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_clear_stack( GNOME_APPBAR( widget));
}

/* on pointer leaving save recipe button in recipe window. */
void
on_recipe_win_save_button_leave( GtkButton *button,
                                 gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_clear_stack( GNOME_APPBAR( widget));
}

/* on pointer leaving add ingredient button in recipe window. */
void
on_recipe_win_add_button_leave( GtkButton *button,
                                gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_clear_stack( GNOME_APPBAR( widget));
}

/* on pointer leaving delete ingredient button in recipe window. */
void
on_recipe_win_delete_button_leave( GtkButton *button,
                                   gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_clear_stack( GNOME_APPBAR( widget));
}

/* on pointer leaving edit ingredient button in recipe window. */
void
on_recipe_win_edit_button_leave( GtkButton *button,
                                 gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_clear_stack( GNOME_APPBAR( widget));
}

/* on pointer leaving nutrient composition  button in recipe window. */
void
on_recipe_win_nutr_comp_button_leave( GtkButton *button,
                                      gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_clear_stack( GNOME_APPBAR( widget));
}

/* on pointer leaving nutrition goal button in recipe window. */
void
on_recipe_win_nutr_goal_button_leave( GtkButton *button,
                                      gpointer   user_data)
{
	GtkWidget *widget = glade_xml_get_widget( xml, "recipe_win_status_msg");
	gnome_appbar_clear_stack( GNOME_APPBAR( widget));
}

/* When the "Nutrients" button is released in the recipe window, show
 * the nutritional composition dialog. */
void
on_recipe_win_nutr_comp_button_released( GtkButton *button,
                                         gpointer   user_data)
{
	recipe->ingredient_clist = (GtkCList *)
			glade_xml_get_widget( xml, "recipe_win_ingredient_clist");
	recipe->no_serv = gtk_entry_get_text( GTK_ENTRY(
			glade_xml_get_widget( xml, "recipe_win_no_serv_entry")));

	if ( !all_digits( recipe->no_serv))
	{
		gnutr_show_msg_no_num_serv();
		return;
	}

	gnutr_show_nutr_comp_dlg();
}

/* When the "Goals" button is released in the recipe window, show
 * the nutrient goals dialog. */
void
on_recipe_win_nutr_goal_button_released( GtkButton *button,
                                         gpointer   user_data)
{
	gnutr_show_nutr_goal_dlg();
}

/* Save a recipe when "save" is selected from the recipe 
 * window menu item. */
void
on_recipe_win_save_activate( GtkMenuItem *menuitem,
                             gpointer     user_data)
{
	gchar *recipe_name = gtk_entry_get_text( GTK_ENTRY(
			glade_xml_get_widget( xml, "recipe_win_recipe_name_entry")));
	gchar *no_serv = gtk_entry_get_text( GTK_ENTRY(
			glade_xml_get_widget( xml, "recipe_win_no_serv_entry")));

	/* Check that the recipe name is defined. */
	if ( empty_text( recipe_name))
	{
		gnutr_show_msg_no_recipe_name();
		return;
	}

	/* Check that the number of servings is defined. */
	if ( !all_digits( no_serv))
	{
		gnutr_show_msg_no_num_serv();
		return;
	}
	
	/* If there is a current working recipe->file_name, ask if it is be
	 * over written, else open the file dialog. */
	if ( recipe->file_name != NULL)
	{
		if ( g_file_exists( recipe->file_name))
		{
			/* warn that the file exists. Over writing existing file? */
			gnutr_show_file_exists_dlg();
		}
	}
	else
	{
		gnutr_show_file_save_dlg();
	}
}

/* Open the file dialog when "save as" is selected from the recipe
 * window menu bar. */
void
on_recipe_win_save_as_activate( GtkMenuItem *menuitem,
                                gpointer     user_data)
{
	gnutr_show_file_save_dlg();
}


/* When the "New" button is released on the recipe window AppBar,
 * ask if current recipe is to be saved. */
void
on_recipe_win_new_button_released( GtkButton *button,
                                   gpointer   user_data)
{
	if ( recipe->no_ingredients !=0)
	{
		gnutr_show_save_cur_recipe_dlg();
	}
	else
	{
		gnutr_free_recipe();
	}
}

/* When the "Save" button is released on the AppBar of the recipe window. */
void
on_recipe_win_save_button_released( GtkButton *button,
                                    gpointer   user_data)
{
	gchar *recipe_name = gtk_entry_get_text( GTK_ENTRY(
			glade_xml_get_widget( xml, "recipe_win_recipe_name_entry")));
	gchar *no_serv = gtk_entry_get_text( GTK_ENTRY(
			glade_xml_get_widget( xml, "recipe_win_no_serv_entry")));

	/* Check that the recipe name is defined. */
	if ( empty_text( recipe_name))
	{
		gnutr_show_msg_no_recipe_name();
		return;
	}

	/* Check that the number of servings is defined. */
	if ( !all_digits( no_serv))
	{
		gnutr_show_msg_no_num_serv();
		return;
	}

	/* If there is a current working recipe->file_name, ask if it is be
	 * over written, else open the file dialog. */
	if ( recipe->file_name != NULL)
	{
		if ( g_file_exists( recipe->file_name))
		{
			/* warn that the file exists. Over writing existing file? */
			gnutr_show_file_exists_dlg();
		}
	}
	else
	{
		gnutr_show_file_save_dlg();
	}
}

/* read recipe from file. */
gboolean
gnutr_open_recipe_file( gchar *fn)
{
	GList *food_glist = gnutr_ret_food_glist();
	GtkWidget *name_entry = glade_xml_get_widget( 
			xml, "recipe_win_recipe_name_entry");
	GtkWidget *no_serv_entry =  glade_xml_get_widget( 
			xml, "recipe_win_no_serv_entry");

	gtk_clist_clear( recipe->ingredient_clist); 

	g_return_val_if_fail( fn !=NULL, FALSE);

	gnutr_read_recipe( fn, &recipe, food_glist);

	/* store name of the read file. */
	recipe->file_name = g_strdup( fn);

	gtk_entry_set_text( GTK_ENTRY( name_entry), recipe->name);
	gtk_entry_set_text( GTK_ENTRY( no_serv_entry), recipe->no_serv);

	return TRUE;
}

/* save recipe to file. */
gboolean
gnutr_save_recipe_to_file( gchar *fn)
{
	GtkWidget *name_entry = glade_xml_get_widget( 
			xml, "recipe_win_recipe_name_entry");
	GtkWidget *no_serv_entry =  glade_xml_get_widget( 
			xml, "recipe_win_no_serv_entry");

	recipe->name = gtk_entry_get_text( GTK_ENTRY( name_entry));
	recipe->no_serv = gtk_entry_get_text( GTK_ENTRY( no_serv_entry));

	g_return_val_if_fail( fn !=NULL, FALSE);

	gnutr_write_recipe( fn, recipe);

	return TRUE;
}

/* callback when window is destroyed by the window manager, or FALSE
 * is returned from the delete_event. */
void
on_recipe_win_destroy( GtkWidget *widget,
                       gpointer   user_data)
{
	GList *food_glist = gnutr_ret_food_glist();
	gnutr_free_recipe();
	gnutr_free_food_glist( &food_glist);
	gtk_main_quit();
}

/* callback usually given when window is closed by window manager. */
gint
on_recipe_win_delete_event( GtkWidget *widget,
                            GdkEvent  *event,
                            gpointer   user_data)
{
	return FALSE;
}

/* return a pointer to the recipe. */
Recipe_t *
gnutr_ret_recipe()
{
	return recipe;
}
