/*  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 <gnome-xml/tree.h>
#include <gnome-xml/parser.h>
#include <ctype.h>

#include "text_util.h"
#include "food.h"
#include "recipe.h"
#include "nutrgoal_io.h"
#include "recipe_win.h"
#include "support.h"
#include "search_dlg.h"

static void search_food_glist( GtkCList *, gchar *, gchar *);
static gint get_food_measure_num(char *);

static Food_t *selected_food = NULL;

/* Show the food selection/search dialog. */
void
on_mw_add_fd_released( GtkButton *button,
                       gpointer   user_data)
{
	GList *desc_list = NULL, *list_ptr, *measure_text_glist = NULL;
	GladeXML *xml =gnutr_ret_xml();
	GtkWidget *search_dialog = glade_xml_get_widget( xml, "srch_dlg");
	GtkWidget *combo1 = glade_xml_get_widget( xml, "srch_dlg_fd_gp_combo");

	GList *food_group_glist = gnutr_create_food_group_glist();

	/* Reset any text entries to empty. */
	GtkWidget *entry1 = glade_xml_get_widget( xml, "srch_dlg_srch_fd_entry");
	GtkWidget *entry2 = glade_xml_get_widget( xml, "srch_dlg_result_entry");
	GtkWidget *entry3 = glade_xml_get_widget( xml, "srch_dlg_amount_entry");
	GtkWidget *combo2 = glade_xml_get_widget( xml, "srch_dlg_measure_combo");

	measure_text_glist = g_list_append( measure_text_glist, "");
	gtk_combo_set_popdown_strings( GTK_COMBO( combo2), measure_text_glist);
	gtk_entry_set_text( GTK_ENTRY( entry1), "");
	gtk_entry_set_text( GTK_ENTRY( entry2), "");
	gtk_entry_set_text( GTK_ENTRY( entry3), "");

	/* extract the food group descriptions and put in the combo box. */
	list_ptr = g_list_first( food_group_glist);
	while( list_ptr)
	{
		desc_list = g_list_prepend( desc_list,
				(( Food_Group_t *)list_ptr->data)->gp_desc);	

		list_ptr = g_list_next( list_ptr);
	}

	gtk_combo_set_popdown_strings( GTK_COMBO( combo1), desc_list);

	gnutr_free_food_group_glist( &food_group_glist);

	/* show the search dialog. */
	gtk_widget_show( search_dialog);
}

/* Create a new clist of the foods in the Search Dialog that match the 
 * search criteria. */
static void
search_food_glist( GtkCList *srch_dlg_clist, gchar *search_string, 
                   gchar *fd_gp_no)
{
	GList *list_ptr;
	Food_t *food = NULL;
	GList *food_glist = gnutr_ret_food_glist();

	list_ptr = g_list_first( food_glist);

	gtk_clist_freeze( srch_dlg_clist);

	while( list_ptr)
	{
		food = ( Food_t *)list_ptr->data;

		/* Is the food in the selected food group, or has the group
		 * "All Foods" been selected? */
		if( strcmp( fd_gp_no, food->group->gp_no) == 0 || 
			strcmp( fd_gp_no, "0001\0") == 0) 
		{
			if( food_search_match( search_string, food->desc->fd_desc))
			{
				gtk_clist_prepend( srch_dlg_clist, &food->desc->fd_desc); 
				gtk_clist_set_row_data( srch_dlg_clist, 0, ( gpointer)food);
			}
		}
		list_ptr = g_list_next( list_ptr);
	}

	gtk_clist_thaw( srch_dlg_clist);
}

/* When the search button is pressed in the Search Dialog, find the foods
 * that match the search string, and put in a clist. */
void
on_srch_dlg_srch_button_clicked( GtkButton *button,
                                 gpointer   user_data)
{
	gchar *fd_gp_desc, *fd_gp_no, *search_string;
	GladeXML *xml =gnutr_ret_xml();
	GtkWidget *srch_entry = glade_xml_get_widget( 
			xml, "srch_dlg_srch_fd_entry");
	GtkWidget *fd_gp_entry = glade_xml_get_widget(
			xml, "srch_dlg_fd_gp_combo_entry");
	GtkCList *clist = (GtkCList *)
			glade_xml_get_widget( xml, "srch_dlg_result_clist");

	search_string = gtk_entry_get_text( GTK_ENTRY( srch_entry));
	fd_gp_desc = gtk_entry_get_text( GTK_ENTRY( fd_gp_entry));
	
	/* Free the old clist, if any. */
	gtk_clist_clear( clist);

	/* Find out the food group number from its selected description. */
	fd_gp_no = gnutr_find_food_group_number( fd_gp_desc);

	/* Form a clist of foods that match the search criteria. */
	search_food_glist( clist, search_string, fd_gp_no);
}

/*  Add the selected food in the clist to the text entry. */
void
on_srch_dlg_result_clist_select_row( GtkCList  *clist,
                                     gint       row,
                                     gint       column,
                                     GdkEvent  *event,
                                     gpointer   user_data)
{
	gchar *food_desc;
	GladeXML *xml =gnutr_ret_xml();
	GtkWidget *entry = glade_xml_get_widget( xml, "srch_dlg_result_entry");

	gtk_clist_get_text( clist, row, 0, &food_desc);
	selected_food = (Food_t *)gtk_clist_get_row_data( clist, row);

	gtk_entry_set_text( GTK_ENTRY( entry), food_desc);
}

/* When the selected food in the search dialog is changed, 
 * also change the measure_combo to list the measures for the new food. */
void
on_srch_dlg_result_entry_changed( GtkEditable *editable,
                                  gpointer     user_data)
{
	GladeXML *xml =gnutr_ret_xml();
	gchar *food_name = gtk_entry_get_text( GTK_ENTRY(
				glade_xml_get_widget( xml, "srch_dlg_result_entry")));

	if ( strcmp( food_name, "") == 0) return;

	{
		gint i, no_measures;
		gchar *measure = NULL;
		GList *measure_text_glist;
		GtkWidget *combo = glade_xml_get_widget( xml, "srch_dlg_measure_combo");

		measure_text_glist = NULL;
		no_measures = selected_food->no_msre;

		for( i=0; i<no_measures; i++)
		{
			measure = selected_food->msre[i]->msre_desc;
			measure_text_glist = g_list_append( measure_text_glist, measure);
		}

		gtk_combo_set_popdown_strings( GTK_COMBO( combo), measure_text_glist);

		g_list_free( measure_text_glist);
	}
}

/* When the measure is changed in the search dialog, reset the amount. */
void
on_srch_dlg_measure_combo_entry_changed( GtkEditable *measure_combo_entry,
                                         gpointer     user_data)
{
	GladeXML *xml =gnutr_ret_xml();
	GtkWidget *entry = glade_xml_get_widget( xml, "srch_dlg_amount_entry");
	gtk_entry_set_text( GTK_ENTRY( entry), "1\0");
}

/* a function that finds the selected measure number from its
 * description. */
static gint
get_food_measure_num(char *string)
{
	gint i;

	g_return_val_if_fail( string != NULL, -1);

	if( strcmp( string, "") == 0 ) return -2;

	for	( i=0; i<selected_food->no_msre; i++)
	{
		if ( strcmp( string, selected_food->msre[i]->msre_desc) == 0)
			return i;
	}
	g_assert_not_reached();
	return 0;
}

/* Exit the Search Dialog with the "OK" button. Gather the necessary
 * data for the food clist in the main application window. */
void
on_srch_dlg_ok_button_released( GtkButton *srch_dlg_ok_button,
                                gpointer   user_data)
{
	GtkWidget *entry;
	gchar *string, *text[3];
	gint i, row = -1;
	GladeXML *xml =gnutr_ret_xml();
	Recipe_t *recipe = gnutr_ret_recipe();

	GtkCList *srch_dlg_clist = (GtkCList *)
			glade_xml_get_widget( xml, "srch_dlg_result_clist");
	GtkWidget *search_dialog = glade_xml_get_widget( xml, "srch_dlg");

	/* food name. */
	entry = glade_xml_get_widget( xml, "srch_dlg_result_entry");
	string = gtk_entry_get_text( GTK_ENTRY( entry));
	if ( strcmp( string, "") == 0)
	{
		/* check that a food has been selected to add to the recipe
	 	* clist. If not just hide the dialog and return. */
		gtk_widget_hide( search_dialog);
		return;
	}
	else
	{
		text[2] = g_strdup( string);
	}

	/* amount. */
	entry = glade_xml_get_widget( xml, "srch_dlg_amount_entry");
	string = gtk_entry_get_text( GTK_ENTRY( entry));
	text[0] = g_strdup( string);

	/* measure. */
	entry = glade_xml_get_widget( xml, "srch_dlg_measure_combo_entry");
	string = gtk_entry_get_text( GTK_ENTRY( entry));
	text[1] = g_strdup( string);

	/* find the selected measure number from its name. */
	selected_food->sel_msre = get_food_measure_num( string);

	/* Does the selected_food already exist in the recipe clist? 
	 * If so, overwrite, else, append. */

	row = gtk_clist_find_row_from_data( recipe->ingredient_clist,
			( gpointer)selected_food);

	if ( row == -1 )
	{
		/* append visible text to recipie clist. */
		gtk_clist_append( recipe->ingredient_clist, text);

		/* append invisible selected_food gpointer data to recipie clist. */
		gtk_clist_set_row_data( recipe->ingredient_clist, 
				recipe->no_ingredients++,
				( gpointer)selected_food);
	}
	else
	{
		/* insert visible text. */
		gtk_clist_insert( recipe->ingredient_clist, row, text);
		/* insert hidden data. */
		gtk_clist_set_row_data( recipe->ingredient_clist, row,
				( gpointer)selected_food);

		/* remove old ingredient from clist. */
		gtk_clist_remove( recipe->ingredient_clist, row+1);
	}

	/* Free allocated memory. */
	gtk_clist_clear( srch_dlg_clist);
	for ( i=0; i<3; i++) g_free( text[i]);

	/* Hide the search dialog. */
	gtk_widget_hide( search_dialog);
}

/* Exit the Search Dialog with "Cancel" button. */
void
on_srch_dlg_cancel_button_released( GtkButton *srch_dlg_cancel_button,
                                    gpointer   user_data)
{	
	GladeXML *xml =gnutr_ret_xml();
	GtkWidget *search_dialog = glade_xml_get_widget( xml, "srch_dlg");
	GtkCList *srch_dlg_clist = (GtkCList *)
			glade_xml_get_widget( xml, "srch_dlg_result_clist");

	/* Free data in search dialog clist. */
	gtk_clist_clear( srch_dlg_clist);

	gtk_widget_hide( search_dialog);
}


/* 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_mw_edit_released                    (GtkButton       *button,
                                        gpointer         user_data)
{
	GList *desc_list = NULL, *list_ptr;
	gchar *amount, *measure, *food_desc;
	GladeXML *xml =gnutr_ret_xml();
	Recipe_t *recipe = gnutr_ret_recipe();

	GtkWidget *search_dialog = glade_xml_get_widget( xml, "srch_dlg");
	GtkWidget *combo1 = glade_xml_get_widget( xml, "srch_dlg_fd_gp_combo");

	GList *food_group_glist = gnutr_create_food_group_glist();

	/* Reset any text entries to empty. */
	GtkWidget *entry1 = glade_xml_get_widget( xml, "srch_dlg_srch_fd_entry");
	GtkWidget *entry2 = glade_xml_get_widget( xml, "srch_dlg_result_entry");
	GtkWidget *entry3 = glade_xml_get_widget( xml, "srch_dlg_amount_entry");
	GtkWidget *combo2 = glade_xml_get_widget( xml, "srch_dlg_measure_combo");

	/* check that an ingredient has been selected. */
	if ( recipe->selected_row == -1)
	{
		GtkWidget *message = glade_xml_get_widget( xml, "nis_msgbox");
		gnome_dialog_close_hides( GNOME_DIALOG( message), TRUE);
	 	gtk_widget_show( message);
		return;
	}
	else
	{
		selected_food = (Food_t *)gtk_clist_get_row_data( 
				recipe->ingredient_clist, recipe->selected_row);

		gtk_clist_get_text( recipe->ingredient_clist, 
				recipe->selected_row, 0, &amount);
		gtk_clist_get_text( recipe->ingredient_clist, 
				recipe->selected_row, 1, &measure);
		gtk_clist_get_text( recipe->ingredient_clist, 
				recipe->selected_row, 2, &food_desc);
	}

	/* set the text entries. */

	gtk_entry_set_text( GTK_ENTRY( entry1), "");

	/* calls: on_srch_dlg_result_entry_changed()  - this also
	 * puts the list of items into the food measures combo box. */
	gtk_entry_set_text( GTK_ENTRY( entry2), food_desc);

	/* extract the food group descriptions and put in the food
	 * group combo box. */
	list_ptr = g_list_first( food_group_glist);
	while( list_ptr)
	{
		desc_list = g_list_prepend( desc_list,
				(( Food_Group_t *)list_ptr->data)->gp_desc);	

		list_ptr = g_list_next( list_ptr);
	}

	gtk_combo_set_popdown_strings( GTK_COMBO( combo1), desc_list);

	/* set the remaining text entries. */

	/* calls: on_srch_dlg_measure_combo_entry_changed() which
	 * resets the amount to one. */
	gtk_entry_set_text( GTK_ENTRY( GTK_COMBO( combo2)->entry), measure);

	gtk_entry_set_text( GTK_ENTRY( entry3), amount);

	gnutr_free_food_group_glist( &food_group_glist);

	/* show the search dialog. */
	gtk_widget_show( search_dialog);
}
