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

#include "text_util.h"
#include "food.h"
#include "recipe.h"

static void read_ingredient_from_xml( xmlNodePtr, GtkCList **, gint, GList *);
static void write_ingredient_to_xml( xmlNodePtr, GtkCList *, gint);
static void write_food_to_xml( xmlNodePtr, Food_t *);
static Food_t * read_food_from_xml( xmlNodePtr, GList *);

static void
write_food_to_xml( xmlNodePtr xmlnode, Food_t *food)
{
	xmlNodePtr newxml;

	g_return_if_fail( xmlnode != NULL);
	g_return_if_fail( food != NULL);

 	newxml = xmlNewChild( xmlnode, NULL, "Food", NULL);

	xmlSetProp( newxml, "food_no", food->desc->fd_no);
	xmlSetProp( newxml, "selected_msre", itoa( food->sel_msre));
}

static void
write_ingredient_to_xml( xmlNodePtr xmlnode, GtkCList *clist, gint row)
{
	xmlNodePtr newxml;
	Food_t *food;
	gchar *text[3];

	g_return_if_fail( xmlnode != NULL);
	g_return_if_fail( clist != NULL);

	/* make a new xml node. */
 	newxml = xmlNewChild( xmlnode, NULL, "Ingredient", NULL);

	gtk_clist_get_text( clist, row, 0, &text[0]); 
	gtk_clist_get_text( clist, row, 1, &text[1]); 
	gtk_clist_get_text( clist, row, 2, &text[2]); 

	/* set node properties. */
	xmlSetProp( newxml, "amount", text[0]);
	xmlSetProp( newxml, "measure", text[1]);
	xmlSetProp( newxml, "food", text[2]);

	food = (Food_t *)gtk_clist_get_row_data( clist, row);

	write_food_to_xml( newxml, food);
}

gboolean
gnutr_write_recipe( gchar *fn, Recipe_t *recipe)
{
	xmlDocPtr doc;
	xmlNodePtr newxml;
	gint row = 0;

	/* create a new xml document with version 1.0 */
	doc = xmlNewDoc("1.0");

	/* create a new root node "Recipe" */
	doc->root = xmlNewDocNode( doc, NULL, "Gnutrition", NULL);

 	newxml = xmlNewChild( doc->root, NULL, "Recipe", NULL);
	xmlSetProp( newxml, "Name", recipe->name);
	xmlSetProp( newxml, "Servings", recipe->no_serv);
	xmlSetProp( newxml, "NoIngredients", itoa( recipe->no_ingredients));

	/* write a list of the ingredients. */
	while ( row < recipe->no_ingredients ) 
	{
		write_ingredient_to_xml( newxml, recipe->ingredient_clist, row);
		row++;
	}

	if( xmlSaveFile( fn, doc) == -1)
	{
		xmlFreeDoc( doc);
		return FALSE;
	}

	xmlFreeDoc( doc);

	return TRUE;
}

static Food_t *
read_food_from_xml( xmlNodePtr cur, GList *food_glist)
{
	gchar *food_no, *selected_msre;
	Food_t *food;
	GList *list_ptr;
	
	food_no = xmlGetProp( cur, "food_no");
	selected_msre = xmlGetProp( cur, "selected_msre");

	list_ptr = g_list_first( food_glist);

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

		if ( strcmp( food_no, food->desc->fd_no) == 0)
		{
			food->sel_msre = atoi( selected_msre);	
			return food;
		}

		list_ptr = g_list_next( list_ptr);
	}
	g_assert_not_reached();

	return NULL;
}

static void 
read_ingredient_from_xml( xmlNodePtr cur, GtkCList **clist, gint row,
		GList *food_glist)
{
	Food_t *food;
	gchar *text[3];

	if ( strcmp( cur->name, "Ingredient") !=0)
	{
		fprintf( stderr, "Ingredient Expected but not found.\n");
		return;
	}

	text[0] = g_strdup( xmlGetProp( cur, "amount"));
	text[1] = g_strdup( xmlGetProp( cur, "measure"));
	text[2] = g_strdup( xmlGetProp( cur, "food"));

	gtk_clist_append( *clist, text);

	cur = cur->childs;

	food = read_food_from_xml( cur, food_glist);
	
	gtk_clist_set_row_data( *clist, row, (gpointer)food);
}

gboolean
gnutr_read_recipe( gchar *fn, Recipe_t **recipe, GList *food_glist)
{
	xmlDocPtr doc;
	xmlNodePtr cur;
	gint row = 0;

	doc = xmlParseFile( fn);
	if ( doc == NULL) return FALSE;

	cur = doc->root;
	if ( cur == NULL)
	{
		fprintf( stderr, "empty document\n");
		xmlFreeDoc( doc);
		return FALSE;
	}

	if ( strcmp( cur->name, "Gnutrition") !=0)
	{
		fprintf( stderr, 
				"document of the wrong type, root node != Gnutrition.\n");
		xmlFreeDoc( doc);
		return FALSE;
	}

	cur = cur->childs;
	if ( strcmp( cur->name, "Recipe") !=0)
	{
		fprintf( stderr, "document of the wrong type, Recipe expected.\n");
		xmlFreeDoc( doc);
		return FALSE;
	}

	(*recipe)->name = xmlGetProp( cur, "Name");
	(*recipe)->no_serv = xmlGetProp( cur, "Servings");
	(*recipe)->no_ingredients = atoi( xmlGetProp( cur, "NoIngredients"));

	cur = cur->childs;

	while ( cur !=NULL )
	{
		read_ingredient_from_xml( cur, &((*recipe)->ingredient_clist), row,
				food_glist);
		cur = cur->next;
		row++;
	}

	xmlFreeDoc( doc);

	return TRUE;
}
