
/*
 * Dlume
 *
 * Copyright (C) 2003-2004 Tomasz M±ka
 *
 * 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.
 */


#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/stat.h>
#include <libxml/tree.h>
#include <libxml/parser.h>

#include "data.h"
#include "prefs.h"

recordstr *rdata;
gpointer data;
GSList *next, *node, *cur;
GSList *list;
guint nLength;
gint records;

gchar *fields[] = {
	"first_name", "last_name", "nickname", "birthday", "address", "post_code",
	"city", "state", "country", "home_phone_1", "home_phone_2",
	"home_phone_3", "home_phone_4", "work_phone_1", "work_phone_2",
	"work_phone_3", "work_phone_4", "cell_phone_1", "cell_phone_2",
	"cell_phone_3", "cell_phone_4", "email_1", "email_2",
	"email_3", "email_4", "url_1", "url_2",
	"url_3", "url_4", "notes"
};

recordstr rec_entry;

gpointer fields_ptr[]= {
	rec_entry.first_name, rec_entry.last_name, rec_entry.nickname,
	rec_entry.birthday, rec_entry.address, rec_entry.post_code,
	rec_entry.city, rec_entry.state, rec_entry.country,
	rec_entry.home_phone_1, rec_entry.home_phone_2,
	rec_entry.home_phone_3, rec_entry.home_phone_4,
	rec_entry.work_phone_1, rec_entry.work_phone_2, rec_entry.work_phone_3,
	rec_entry.work_phone_4, rec_entry.cell_phone_1,
	rec_entry.cell_phone_2, rec_entry.cell_phone_3, rec_entry.cell_phone_4,
	rec_entry.email_1, rec_entry.email_2, rec_entry.email_3,
	rec_entry.email_4, rec_entry.url_1, rec_entry.url_2,
	rec_entry.url_3, rec_entry.url_4, rec_entry.notes
};

gint fields_size[] = {
	size_name, size_name, size_name, size_birthday, size_address, size_post_code,
	size_city,	size_state, size_country, size_phone, size_phone,
	size_phone, size_phone, size_phone, size_phone,
	size_phone, size_phone, size_phone, size_phone,
	size_phone, size_phone, size_email, size_email,
	size_email, size_email, size_url, size_url,
	size_url, size_url, size_notes
};

/*----------------------------------------------------------------------------*/

gchar* get_data_filename (gchar *config_dir_d, gchar *config_filename_d)
{
static gchar filename[MAX_PATH];
static gchar cfgdir[MAX_PATH];
struct stat cfg;

	strncpy (cfgdir, getenv ("HOME"), MAX_PATH);
	strncat (cfgdir, slash, MAX_PATH);
	strncat (cfgdir, config_dir_d, MAX_PATH);

	if(stat(cfgdir, &cfg) < 0)
		mkdir(cfgdir, S_IRUSR | S_IWUSR | S_IXUSR);

	strncpy (filename, cfgdir, MAX_PATH);
	strncat (filename, slash, MAX_PATH);
	strncat (filename, config_filename_d, MAX_PATH);

	return filename;
}

/*----------------------------------------------------------------------------*/

gint clear_record(recordstr *entry)
{
	memset(&entry, 0, sizeof(recordstr));
	return 0;
}

/*----------------------------------------------------------------------------*/

gint data_init(void)
{
	list = NULL;
	return 0;
}

/*----------------------------------------------------------------------------*/

gint data_close(void)
{

	node = list;

	while (node) {
		free(node->data);
		cur = node;
		node = node->next;
		g_slist_remove (list, cur->data);
	}

	return 0;
}

/*----------------------------------------------------------------------------*/

gint data_get_records(void)
{
gint i;

	for (node = list, i = 0; node; node = node->next, i++);
	return i;

}

/*----------------------------------------------------------------------------*/

gint data_add_record(recordstr *entry)
{
	rdata = calloc(1, sizeof(recordstr));
	g_assert(rdata!=NULL);

	memcpy(rdata, entry, sizeof(recordstr));
	list = g_slist_append (list, rdata);

	return 0;
}

/*----------------------------------------------------------------------------*/

gint data_remove_record(gint k)
{
recordstr *rdata;

	rdata = g_slist_nth_data (list, k);
	list = g_slist_remove (list, rdata);

	return 0;
}

/*----------------------------------------------------------------------------*/

gint data_read(void)
{
xmlDocPtr doc;
xmlNodePtr cur, acur;
xmlChar *prop, *key;
gint i;


	records = 0;

	if((doc = xmlParseFile(get_data_filename(".clay", DATAFILE)))) {

		if(!(cur = xmlDocGetRootElement(doc))) {
			g_print("WARNING: datafile is empty.\n");
		}

		if(!xmlStrcmp(cur->name, "data")) {

			prop = xmlGetProp(cur, "records");
			if(prop) records = atoi(prop);

			cur = cur->xmlChildrenNode;
			while (cur != NULL) {

				if(!xmlStrcmp(cur->name, "record")) {

				    memset(&rec_entry, 0, sizeof(recordstr));

					acur = cur->xmlChildrenNode;
					while (acur != NULL) {

						for(i=0; i < nfields; i++) {
							if(!xmlStrcmp(acur->name, fields[i])) {
								key = xmlNodeListGetString(doc, acur->xmlChildrenNode, 1);

								if(key!=NULL) {

									if(i==FIRST_NAME || i==LAST_NAME)
										key[0] = toupper(key[0]);

									strncpy(fields_ptr[i], key, fields_size[i]-1);
									strcat(fields_ptr[i], "\0");
								}
							}
						}

						acur = acur->next;
					}

					data_add_record(&rec_entry);
				}

				cur = cur->next;
			}
		}
	}

	return records;
}

/*----------------------------------------------------------------------------*/

gint data_write(void)
{
xmlDocPtr doc;
xmlNodePtr record_node;
gchar c[10];
gint i, j;


	doc = xmlNewDoc("1.0");
	doc->xmlRootNode = xmlNewDocNode(doc, NULL, "data", NULL);

	i = 0;
	node = list;

	while (node) {

		xmlAddChild(doc->xmlRootNode, xmlNewText("\n"));
		record_node = xmlNewChild(doc->xmlRootNode, NULL, "record", NULL);
		xmlAddChild(record_node, xmlNewText("\n"));

		rdata = node->data;
		memcpy(&rec_entry, rdata, sizeof(recordstr));

		for(j=0; j < nfields; j++)
			if(strlen(fields_ptr[j])) {
				xmlAddChild(record_node, xmlNewText("\t"));
				xmlNewChild(record_node, NULL, fields[j], fields_ptr[j]);
				xmlAddChild(record_node, xmlNewText("\n"));
			}

			i++;
			node = node->next;
	}

	snprintf(c, 10, "%d", i);
	xmlSetProp(doc->xmlRootNode, "records", c);
	xmlAddChild(doc->xmlRootNode, xmlNewText("\n"));

	xmlSaveFile(get_data_filename(".clay", DATAFILE), doc);
	xmlFreeDoc(doc);

	return 0;
}

/*----------------------------------------------------------------------------*/

gint find_record(gchar *f, gchar *l)
{
GSList *node;
recordstr *rdata;
gint i, p, s1, s2;

	p = -1;
		
	i = s1 = s2 = 0;

	if(f) s1 = strlen(f);
	if(l) s2 = strlen(l);

	node = list;

	while(node) {

		rdata = node->data;

		if(s1 && s2 && rdata && !strcmp (f, rdata->first_name) && !strcmp (l, rdata->last_name))
			p = i;

			else if(s1 && !s2 && rdata && !strcmp (f, rdata->first_name))
				p = i;

				else if(!s1 && s2 && rdata && !strcmp (l, rdata->last_name))
					p = i;

		i++;
		node = node->next;

	}

	return p;
}

/*------------------------------------------------------------------------------*/

void data_print_csv_entry(FILE *filehandle, recordstr *rdata)
{
gchar a, *buffer;
gchar tmp_buffer_1[size_notes], tmp_buffer_2[size_notes];
gint i, j, k, l, m, e;

	memcpy(&rec_entry, rdata, sizeof(recordstr));

	for(k=0; k < nfields-1; k++) {

		e = (config.selected_fields >> k) & 1;

		if(e) {

			buffer = (gchar *)fields_ptr[k];
			l = strlen(buffer);

			if(l) {

				/* 1 */

				for(i=j=0;i<l;i++)
					if(buffer[i]=='"') j = 1;

				m = i = 0;

				if(j) tmp_buffer_1[m++] = '"';

				do {
					a = buffer[i++];
					if(a=='"') tmp_buffer_1[m++] = '"';
					tmp_buffer_1[m++] = a;
				} while (a!='\0');

				if(j) {
					tmp_buffer_1[m-1] = '"';
					tmp_buffer_1[m] = '\0';
				}

				/* 2 */

				l = strlen(tmp_buffer_1);

				for(i=j=0;i<l;i++)
					if(tmp_buffer_1[i]==',') j = 1;

				m = i = 0;

				if(j) tmp_buffer_2[m++] = '"';

				do {
					a = tmp_buffer_1[i++];
					tmp_buffer_2[m++] = a;
				} while (a!='\0');

				if(j) {
					tmp_buffer_2[m-1] = '"';
					tmp_buffer_2[m] = '\0';
				}
			
			    fprintf(filehandle, "%s", tmp_buffer_2);

			}

			if(k != nfields-1) fprintf(filehandle, ",");
		}
	}
	fprintf(filehandle, "\n");
}

/*------------------------------------------------------------------------------*/

void data_print_html_entry(FILE *filehandle, recordstr *rdata)
{
gchar a, tmp_buffer[size_notes], *buffer;
gint i, j, k, l, e;

	memcpy(&rec_entry, rdata, sizeof(recordstr));

	for(k=0; k < nfields-1; k++) {

		e = (config.selected_fields >> k) & 1;

		if(e) {

			fprintf(filehandle, "\t<td>");

			buffer = (gchar *)fields_ptr[k];
			l = strlen(buffer);

			if(l) {

				for(i=j=0;i<l;i++) {

					a = buffer[i];

					if(a==' ') {
						tmp_buffer[j] = '\0';
						strcat(tmp_buffer, "&nbsp;");
						j += 6;
					} else
						tmp_buffer[j++] = a;

				}

				tmp_buffer[j] = '\0';

				switch (k)
				{
					case EMAIL_1:
					case EMAIL_2:
					case EMAIL_3:
					case EMAIL_4:
						fprintf(filehandle, "<a href=\"mailto:%s\">%s</a>", tmp_buffer, tmp_buffer);
						break;
					case URL_1:
					case URL_2:
					case URL_3:
					case URL_4:
						fprintf(filehandle, "<a href=\"%s\">%s</a>", tmp_buffer, tmp_buffer);
						break;
					default:
						fprintf(filehandle, "%s", tmp_buffer);
				}
			} else
				fprintf(filehandle, "&nbsp;");

			fprintf(filehandle, "</td>\n");

		}
	}

}

/*------------------------------------------------------------------------------*/

