/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/* 
 *
 * Copyright (C) 1999 Bertrand Guiheneuf <Bertrand.Guiheneuf@aful.org> .
 *
 * 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 <config.h> 

#include "mh-uid.h"
#include "camel-log.h"
#include "camel-stream.h"
#include "camel-stream-fs.h"
#include "camel-stream-buffered-fs.h"
#include "gmime-utils.h"
#include "mh-utils.h"

#include <sys/stat.h> 
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

void 
mh_generate_summary (CamelFolder *folder)
{
	CamelMhFolder *mh_folder = CAMEL_MH_FOLDER (folder);
	CamelFolderSummary *summary;
	CamelMessageInfo *message_info;
	CamelFolderInfo *subfolder_info;
	CamelStream *message_stream;
	guint file_number;
	gchar *message_fullpath;
	gchar *directory_path;
	GArray *header_array;
	MhUidCouple *uid_couple;
	Rfc822Header *cur_header;
	int i;
	int n_file;
	GArray *uid_array;

	CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::generate_summary entering \n");

	g_assert (folder);

	directory_path = mh_folder->directory_path;
	if (!directory_path) {
		CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::generate_summary folder has no directory path\n");
		return;
	}

	summary = camel_folder_summary_new ();
	folder->summary = summary;

	uid_array = mh_folder->uid_array;
	
	if (!uid_array) {
		CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::generate_summary "
				      "no uid list, that probably means there is "
				      "no message in this folder, exiting \n");
		return;
	}
	uid_couple = (MhUidCouple *)uid_array->data;

	for (n_file=0; n_file<uid_array->len; n_file++) {

		file_number = uid_couple->file_number;

		message_info = g_new0 (CamelMessageInfo, 1);
		message_info->uid = g_new0 (guchar, 17);
		strncpy (message_info->uid, uid_couple->uid, 16);


		message_fullpath = g_strdup_printf ("%s/%d", directory_path, file_number);
		message_stream = camel_stream_buffered_fs_new_with_name (message_fullpath, 
									 CAMEL_STREAM_BUFFERED_FS_READ);
		if (!message_stream) {
			CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::generate_summary "
					      "could not open %d for reading\n", message_fullpath);
			g_free (message_fullpath);
			return;
		}
		g_free (message_fullpath);
		
		header_array = get_header_array_from_stream (message_stream);
		gtk_object_unref (GTK_OBJECT (message_stream));
		
		for (i=0; i<header_array->len; i++) {
			cur_header = (Rfc822Header *)header_array->data + i;
			if (!g_strcasecmp (cur_header->name, "subject")) {
				message_info->subject = cur_header->value;
				g_free (cur_header->name);
			} else if (!g_strcasecmp (cur_header->name, "sender")) {
				message_info->date = cur_header->value;
				g_free (cur_header->name);
			} else if (!g_strcasecmp (cur_header->name, "date")) {
				message_info->date = cur_header->value;
				g_free (cur_header->name);
			} else {
				g_free (cur_header->name);
				g_free (cur_header->value);
			}
		}		
		g_array_free (header_array, TRUE);

		summary->message_info_list = g_list_append (summary->message_info_list, message_info);

		/* next message in the uid list */
		uid_couple++;
	}	
	CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::generate_summary leaving \n");

}


void 
mh_save_summary (CamelMhFolder *mh_folder)
{
	GArray *uid_array;
	MhUidCouple *first_uid_couple;
	CamelFolderSummary *summary;
	GList *msg_info_list;
	CamelMessageInfo *msg_info;
	gchar *directory_path = mh_folder->directory_path;
	gchar *summary_file_path;
	gint fd;
	gint i;
	gint field_lgth;
	
	CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::save_summary entering \n");

	summary = CAMEL_FOLDER (mh_folder)->summary;
	if (!summary) return;
	
	summary_file_path = g_strdup_printf ("%s/%s", directory_path, ".camel-summary");
	CAMEL_LOG_FULL_DEBUG ("In the process of writing %s\n", summary_file_path);
	fd = open (summary_file_path, O_WRONLY | O_CREAT );
	
	if (!fd) {
		CAMEL_LOG_FULL_DEBUG ("could not open file %s for writing. Exiting.\n", summary_file_path);
		g_free (summary_file_path);
		return;
	}
	g_free (summary_file_path);

	msg_info_list = summary->message_info_list;
	while (msg_info_list) {
		msg_info = msg_info_list->data;
		/* write subject */
		field_lgth = msg_info->subject ? strlen (msg_info->subject) : 0;
		write (fd, &field_lgth, sizeof (gint));
		if (field_lgth)
			write (fd, msg_info->subject, field_lgth);

		/* write uid */
		field_lgth = msg_info->uid ? strlen (msg_info->uid) : 0;
		write (fd, &field_lgth, sizeof (gint));
		if (field_lgth)
			write (fd, msg_info->uid, field_lgth);

		/* write date */
		field_lgth = msg_info->date ? strlen (msg_info->date) : 0;
		write (fd, &field_lgth, sizeof (gint));
		if (field_lgth)
			write (fd, msg_info->date, field_lgth);

		/* write sender */
		field_lgth = msg_info->sender ? strlen (msg_info->sender) : 0;
		write (fd, &field_lgth, sizeof (gint));
		if (field_lgth)
			write (fd, msg_info->sender, field_lgth);

		msg_info_list = msg_info_list->next;
		
	}
			
	close (fd);

	CAMEL_LOG_FULL_DEBUG ("CamelMhFolder::save_summary leaving \n");
		
}





gint
mh_load_summary (CamelMhFolder *mh_folder)
{
	GArray *uid_array;
	MhUidCouple *first_uid_couple;
	CamelFolderSummary *summary;
	CamelMessageInfo *msg_info;
	gchar *directory_path = mh_folder->directory_path;
	gchar *summary_file_path;
	gint fd;
	gint i;
	gint field_lgth;
	gboolean file_eof;
	gint stat_error;
	struct stat stat_buf;

	summary = CAMEL_FOLDER (mh_folder)->summary;
	if (summary) return 1; /* should we regenerate it ? */
	
	summary_file_path = g_strdup_printf ("%s/%s", directory_path, ".camel-summary");
	CAMEL_LOG_FULL_DEBUG ("In the process of reading %s\n", summary_file_path);
	fd = open (summary_file_path, O_RDONLY);
	/* tests if file exists */
	stat_error = stat (summary_file_path, &stat_buf);

	if (!((stat_error != -1) && S_ISREG (stat_buf.st_mode))) {		
		CAMEL_LOG_FULL_DEBUG ("could not open file %s for reading. Exiting.\n", summary_file_path);
		g_free (summary_file_path);
		return -1;
	}
	g_free (summary_file_path);
	
	for (;;)  {
		/* read subject */
		file_eof = (read (fd, &field_lgth, sizeof (gint)) <= 0);
		if (file_eof) break;
		
		
		/* allcate a summary if needed */
		if (!summary) 
			summary = camel_folder_summary_new ();
		/* allocate a message info struct */
		msg_info = g_new0 (CamelMessageInfo, 1);	
	
		if (!file_eof && (field_lgth > 0)) {			
			msg_info->subject = g_new0 (gchar, field_lgth + 1);
			read (fd, msg_info->subject, field_lgth);
		} else 
			msg_info->subject = NULL;
		
		/* read uid */
		if (!file_eof) file_eof = (read (fd, &field_lgth, sizeof (gint)) <= 0);
		if (!file_eof && (field_lgth > 0)) {		
			msg_info->uid = g_new0 (gchar, field_lgth + 1);
			read (fd, msg_info->uid, field_lgth);
		} else 
			msg_info->uid = NULL;
		
		/* read date */
		if (!file_eof) file_eof = (read (fd, &field_lgth, sizeof (gint)) <= 0);
		if (!file_eof && (field_lgth > 0)) {			
			msg_info->date = g_new0 (gchar, field_lgth + 1);
			read (fd, msg_info->date, field_lgth);
		} else 
			msg_info->date = NULL;
		
		/* read sender */
		if (!file_eof) file_eof = (read (fd, &field_lgth, sizeof (gint)) <= 0);
		if (!file_eof && (field_lgth > 0)) {			
			msg_info->sender = g_new0 (gchar, field_lgth + 1);
			read (fd, msg_info->sender, field_lgth);
		} else 
			msg_info->sender = NULL;

		summary->message_info_list = g_list_prepend (summary->message_info_list, 
							     msg_info);
	}		
	
	CAMEL_FOLDER (mh_folder)->summary = summary;
			
	close (fd);
	return 1;
}