/*  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 <mysql.h>
#if defined( LIBXML_VERSION) && LIBXML_VERSION >= 20000
	#include <xmlmemory.h>
	#include <libxml/parser.h>
	#include <libxml/tree.h>
	#define root children
	#define childs children
#else
	#include <gnome-xml/parser.h>
	#include <gnome-xml/tree.h>
	#include <gnome-xml/xmlmemory.h>
#endif
#include "text_util.h"
#include "wrap_mysql.h"
#include "init_database.h"

/* called the first time to create database, tables, etc. */
gboolean
initialize_db( char *user, char *password)
{
	char *query, *file_name;
	gboolean success;
	GList *list = NULL, *ptr;
	char *elm;

	g_return_val_if_fail( user, FALSE);
	g_return_val_if_fail( password, FALSE);

	success = connect_db( user, password);
	if ( !success) return FALSE;

	/* success to see if the gnutr_db database already exists. If
	 * it does, just return. */
	query = g_strdup( "SHOW DATABASES");
	list = get_glist_fields_query_db( query);
	g_assert( list);
	g_free( query);

	for ( ptr = list; ptr; ptr = ptr->next) {
		elm = ( char *)list->data;
		if ( strcmp( elm, "gnutr_db") == 0) return TRUE;
	}
	gnutr_free_field_list( list);

	/* create the database. */
	query = g_strdup( "CREATE DATABASE gnutr_db");
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);

	/* use the newly created database. */
	query = g_strdup( "USE gnutr_db");
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);

	/*** BEGIN USDA NUTRIENT DATA TABLES ***/
	/* create food_des table. */
	query = g_strconcat( "CREATE TABLE food_des ", 
		"( fd_no SMALLINT( 5) UNSIGNED NOT NULL, ",
		"fd_gp SMALLINT( 4) UNSIGNED NOT NULL, ",
		"fd_desc CHAR( 200) NOT NULL, ",
		"short_desc CHAR( 60) NOT NULL, ",
		"refuse_desc CHAR( 45), ",
		"refuse FLOAT( 2,0), ",
		"sci_name CHAR( 60), ",
		"n_factor FLOAT( 5,3), ",
		"pro_factor FLOAT( 5,3), ",
		"fat_factor FLOAT( 5,3), ",
		"cho_factor FLOAT( 5,3), ",
		"INDEX (fd_no), INDEX (fd_gp))", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);
	file_name = g_strdup( GNUTRITION_DATADIR "/food_des.txt");
	/* load food_des data from file. */
	query = g_strconcat( "LOAD DATA LOCAL INFILE ", 
		"'", file_name, "' ",
		"INTO TABLE food_des FIELDS TERMINATED BY '^'", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( file_name);
	g_free( query);

	/* create fd_group table. */
	query = g_strconcat( "CREATE TABLE fd_group ",
		"( fd_gp SMALLINT( 4) UNSIGNED NOT NULL, ",
		"gp_desc CHAR( 60) NOT NULL, "
		"INDEX (fd_gp))", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);
	/* load fd_group data from file. */
	file_name = g_strdup( GNUTRITION_DATADIR "/fd_group.txt");
	query = g_strconcat( "LOAD DATA LOCAL INFILE ",
		"'", file_name, "' ",
		"INTO TABLE fd_group FIELDS TERMINATED BY '^'", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( file_name);
	g_free( query);

	/* create measure table. */
	query = g_strconcat( "CREATE TABLE measure ",
		"( msre_no MEDIUMINT( 5) UNSIGNED NOT NULL, ",
		"msre_desc CHAR( 120) NOT NULL, ",
		"INDEX( msre_no) )", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);
	/* load measure data from file. */
	file_name = g_strdup( GNUTRITION_DATADIR "/measure.txt");
	query = g_strconcat( "LOAD DATA LOCAL INFILE ",
		"'", file_name, "' ",
		"INTO TABLE measure FIELDS TERMINATED BY '^'", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( file_name);
	g_free( query);

	/* create nut_data table. */
	query = g_strconcat( "CREATE TABLE nut_data ",
		"( fd_no SMALLINT( 5) UNSIGNED NOT NULL, ",
		"nutr_no SMALLINT( 3) UNSIGNED NOT NULL, ",
		"nutr_val FLOAT( 10,3) NOT NULL, ",
		"sample_ct FLOAT( 5,0) NOT NULL, ",
		"std_error FLOAT( 8,3), ",
		"src_cd CHAR( 2) NOT NULL, "
		"INDEX (fd_no, nutr_no) )", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);
	/* load nut_data data from file. */
	file_name = g_strdup( GNUTRITION_DATADIR "/nut_data.txt");
	query = g_strconcat( "LOAD DATA LOCAL INFILE ",
		"'", file_name, "' ",
		"INTO TABLE nut_data FIELDS TERMINATED BY '^'", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( file_name);
	g_free( query);

	/* create nutr_def table. */
	query = g_strconcat( "CREATE TABLE nutr_def ",
		"( nutr_no SMALLINT(3) UNSIGNED NOT NULL, ",
		"units CHAR(6) NOT NULL, ",
		"tagname CHAR(20) NOT NULL, ",
		"nutr_desc CHAR(60) NOT NULL, ",
		"INDEX (nutr_no) )", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);
	/* load nut_data data from file. */
	file_name = g_strdup( GNUTRITION_DATADIR "/nutr_def.txt");
	query = g_strconcat( "LOAD DATA LOCAL INFILE ",
		"'", file_name, "' ",
		"INTO TABLE nutr_def FIELDS TERMINATED BY '^'", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( file_name);
	g_free( query);

	/* create weight table. */
	query = g_strconcat( "CREATE TABLE weight ",
		"( fd_no SMALLINT(5) UNSIGNED NOT NULL, ",
		"msre_no MEDIUMINT(5) UNSIGNED NOT NULL, ",
		"wgt_val FLOAT(9,2), ",
		"INDEX (fd_no, msre_no) )", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);
	/* load weight data from file. */
	file_name = g_strdup( GNUTRITION_DATADIR "/weight.txt");
	query = g_strconcat( "LOAD DATA LOCAL INFILE ",
		"'", file_name, "' ",
		"INTO TABLE weight FIELDS TERMINATED BY '^'", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( file_name);
	g_free( query);
	/*** END USDA NUTRIENT DATA TABLES ***/

	/*** BEGIN RECIPE TABLES ***/
	/* create recipe table. */
	query = g_strconcat( "CREATE TABLE recipe ",
		"( recipe_no MEDIUMINT(6) UNSIGNED NOT NULL AUTO_INCREMENT, ",
		"recipe_name CHAR(200) NOT NULL, ",
		"no_serv SMALLINT(4) UNSIGNED NOT NULL, ",
		"no_ingr SMALLINT(4) UNSIGNED NOT NULL, ",
		"category_no TINYINT(3) UNSIGNED NOT NULL, ",
		"PRIMARY KEY (recipe_no), ",
		"INDEX (recipe_name( 20), category_no))",
		NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);

	/* create recipe ingredient table. */
	query = g_strconcat( "CREATE TABLE ingredient ",
		"( recipe_no MEDIUMINT(6) NOT NULL, ",
		"amount FLOAT(7,2) NOT NULL, ",
		"msre_no MEDIUMINT(5) UNSIGNED NOT NULL, ",
		"fd_no SMALLINT(5) UNSIGNED NOT NULL, ",
		"INDEX (recipe_no))", 
		NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);

	/* create recipe category table. */
	query = g_strconcat( "CREATE TABLE category ",
		"( category_no TINYINT(3) UNSIGNED NOT NULL, ",
		"category_desc CHAR(40) NOT NULL, ",
		"INDEX (category_no))", 
		NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);
	/* load category data from file. */
	file_name = g_strdup( GNUTRITION_DATADIR "/category.txt");
	query = g_strconcat( "LOAD DATA LOCAL INFILE ",
		"'", file_name, "' ",
		"INTO TABLE category FIELDS TERMINATED BY '^'", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( file_name);
	g_free( query);

	/* create recipe preparation table. */
	query = g_strconcat( "CREATE TABLE preparation ",
		"( recipe_no MEDIUMINT( 6) UNSIGNED NOT NULL, ",
		"prep_time CHAR( 50), ",
		"prep_desc TEXT, ",
		"INDEX (recipe_no))", 
		NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);
	/*** END RECIPE TABLES ***/

	/*** BEGIN PERSON PLAN TABLES ***/
	/* create person table. */
	query = g_strconcat( "CREATE TABLE person ",
		"( person_no SMALLINT(6) UNSIGNED NOT NULL AUTO_INCREMENT ",
		"PRIMARY KEY, ",
		"person_name CHAR(100), INDEX person_name (person_name(10)), ",
		"user_name CHAR(50))", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);

	/* create food_plan table. */
	query = g_strconcat( "CREATE TABLE food_plan ",
		"( person_no SMALLINT(6) UNSIGNED NOT NULL, ",
		"date DATE NOT NULL, ",
		"time TIME NOT NULL, ",
		"amount FLOAT(7,2) NOT NULL, ",
		"msre_no MEDIUMINT(5) UNSIGNED NOT NULL, ",
		"fd_no SMALLINT(5) UNSIGNED NOT NULL)", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);

	/* create recipe_plan table */
	query = g_strconcat( "CREATE TABLE recipe_plan ",
		"( person_no SMALLINT(6) UNSIGNED NOT NULL, ",
		"date DATE NOT NULL, ",
		"time TIME NOT NULL, ",
		"no_portions FLOAT(7,2) NOT NULL, ",
		"recipe_no MEDIUMINT(6) UNSIGNED NOT NULL)", 
		NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);

	/* create personal nutrient goal table */
	query = g_strconcat( "CREATE TABLE nutr_goal ",
		"( person_no SMALLINT(6) UNSIGNED NOT NULL, ",
		"nutr_no SMALLINT(3) UNSIGNED NOT NULL, ",
		"goal_val FLOAT(11,4) NOT NULL)", 
		NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);

	return TRUE;
}

/* set permissions for the user. */ 
void
add_user_db( char *user, char *password)
{
	char *query;
	gboolean success;

	g_return_if_fail( user);
	g_return_if_fail( password);

	/* just grant the user ability to connect ot the database and 
	 * nothing much else. */
	query = g_strconcat( "GRANT USAGE ON *.* TO ", user, 
			"@localhost IDENTIFIED BY '", password, "'", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);

	/* give the user all privileges to the gnutr_db database. */
	query = g_strconcat( "GRANT ALL ON gnutr_db.* TO ", user, 
			"@localhost IDENTIFIED BY '", password, "'", NULL);
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);

	query = g_strdup( "FLUSH PRIVILEGES"); 
	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);
}

/* drops the database. */
void
delete_db()
{
	char *query = g_strdup( "DROP DATABASE gnutr_db"); 
	gboolean success;

	success = no_ret_val_query_db( query);
	g_assert( success);
	g_free( query);
}

char *
get_person_name()
{
	xmlDocPtr doc;
	xmlNodePtr cur;
	char *home = g_strdup( g_get_home_dir());
	char *fn = g_strconcat( home, "/.gnutrition/person_info.xml", NULL);
	char *name = NULL;

#if defined( LIBXML_VERSION) && LIBXML_VERSION >= 20000
	xmlKeepBlanksDefault( 0);
#endif

	/* load the file. */
	doc = xmlParseFile( fn);
	g_free( fn);
	g_free( home);

	/* make a series of checks. */
	if ( doc == NULL) return NULL;

	cur = doc->root;
	if ( cur == NULL) {
		g_warning( "empty document.");
		xmlFreeDoc( doc);
		return NULL;
	}

	if ( strcmp( cur->name, "Gnutrition") != 0 ) {
		g_warning( "document of the wrong type.");
		xmlFreeDoc( doc);
		return NULL;
	}

	cur = cur->childs;
	if ( strcmp( cur->name, "Personal_Info") != 0 ) {
		g_warning( "document of the wrong type.");
		xmlFreeDoc( doc);
		return NULL;
	}

	/* get data from file. */
	cur = cur->childs;
	name = xmlNodeListGetString( doc, cur->childs, 1);

	xmlFreeDoc ( doc);

	g_assert( name);
	return name;
}
