/*
 *  MimeItem manipulation routines
 *  Copyright (C) 2000-2001 Marco Pesenti Gritti
 *
 *  Loading and saving routines
 *  Copyright (C) 2001 Philip Langdale
 *
 *  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, 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 "galeon.h"
#include "mime.h"
#include "misc.h"

#include <string.h>
#include <libgnome/gnome-util.h>
#include <libgnome/gnome-i18n.h>

/* the global list of MimeItems */
GList *mime_types = NULL;

struct { gchar *name; MimeAction action; } default_mimetypes[] =
{
	{ "audio/x-mp3",			MIME_SAVE_TO_DISK },
	{ "audio/x-ogg",			MIME_SAVE_TO_DISK },
	{ "video/mpeg",				MIME_SAVE_TO_DISK },
	{ "video/x-msvideo",			MIME_SAVE_TO_DISK },
	{ "application/x-tar",			MIME_SAVE_TO_DISK },
	{ "application/x-gzip",			MIME_SAVE_TO_DISK },
	{ "application/x-bzip",			MIME_SAVE_TO_DISK },
	{ "application/x-bzip2",		MIME_SAVE_TO_DISK },
	{ "application/x-compressed-tar",	MIME_SAVE_TO_DISK },
	{ "application/x-bzip-compressed-tar",	MIME_SAVE_TO_DISK },
	{ "application/x-tar",			MIME_SAVE_TO_DISK },	
	{ "application/zip",			MIME_SAVE_TO_DISK },	
	{ "application/x-rpm",			MIME_SAVE_TO_DISK },
	{ "application/octet-stream",		MIME_SAVE_TO_DISK },
	{ NULL, MIME_UNKNOWN } /* terminator -- must be last */
};

void
mime_init_defaults (void)
{
	int i;

	for (i = 0; default_mimetypes[i].name != NULL; i++)
	{
		mime_set_action (default_mimetypes[i].name, 
				 default_mimetypes[i].action);
	}
}

MimeItem* mime_item_get (const gchar *mime_type)
{
	GList *l;
	for (l = mime_types; l != NULL; l = l->next)
		if (!strcmp (mime_type, ((MimeItem *) l->data)->name))
			return (MimeItem *)l->data;
	return NULL;
}

MimeAction 
mime_get_action (const gchar *mime_type)
{
	GList *l;
	for (l = mime_types; l != NULL; l = l->next)
		if (!strcmp (mime_type, ((MimeItem *) l->data)->name))
			return ((MimeItem *) l->data)->action;
	return MIME_UNKNOWN;
}

void 
mime_set_action (const gchar *mime_type, MimeAction action)
{
	GList *l;
	MimeItem *newitem;
	gboolean exists = FALSE;

	/* change the value if we already have it in the list */
	for (l = mime_types; l != NULL; l = l->next)
		if (!strcmp (mime_type, ((MimeItem *) l->data)->name))
		{
			exists = TRUE;
			((MimeItem *) l->data)->action = action;
		};
	/* not found, add a new mime type */
	if (!exists)
	{
		newitem = g_new0 (MimeItem, 1);
		newitem->name = g_strdup (mime_type);
		newitem->action = action;
		newitem->helperApp = g_strdup (_("disabled"));
		newitem->terminalHelper = FALSE;
		newitem->urlHelper = FALSE;
		newitem->alwaysUse = FALSE;
		mime_types = g_list_prepend (mime_types, newitem);
	};
}

void 
mime_item_create (const gchar *mime_type, MimeAction action,
		  const gchar *helperApp, gboolean terminalHelper,
		  gboolean urlHelper, gboolean alwaysUse)
{
	GList *l;
	MimeItem *newitem;
	gboolean exists = FALSE;

	/* check if we already have it in the list */
	for (l = mime_types; l != NULL; l = l->next)
		if (!strcmp (mime_type, ((MimeItem *) l->data)->name))
		{
			exists = TRUE;
		}
	/* not found, add a new mime type */
	if (!exists)
	{
		newitem = g_new0 (MimeItem, 1);
		newitem->name = g_strdup (mime_type);
		newitem->action = action;
		newitem->helperApp = g_strdup (helperApp);
		newitem->terminalHelper = terminalHelper;
		newitem->urlHelper = urlHelper;
		newitem->alwaysUse = alwaysUse;
		mime_types = g_list_prepend (mime_types, newitem);
	}
}

MimeItem *
mime_item_clone (MimeItem *m)
{
	MimeItem *r = g_new0 (MimeItem, 1);
	g_return_val_if_fail (m != NULL, NULL);	
	g_return_val_if_fail (m->name != NULL, NULL);
	g_return_val_if_fail (m->helperApp != NULL, NULL);
	r->name = g_strdup (m->name);
	r->action = m->action;
	r->helperApp = g_strdup (m->helperApp);
	r->terminalHelper = m->terminalHelper;
	r->urlHelper = m->urlHelper;
	r->alwaysUse = m->alwaysUse;
	return r;
}

void
mime_item_free (MimeItem *m)
{
	if (m)
	{
		if (m->name) g_free (m->name);
		if (m->helperApp) g_free (m->helperApp);
		g_free (m);
		m = NULL;
	}
}

/**
 * mime_db_save: store the mime database to the standard location
 */
void mime_db_save (void)
{
	GList *m;
	xmlNodePtr root_node;
	xmlNodePtr mime_node;
	xmlDocPtr doc;
	gchar buffer[3];

	gchar *filename = g_concat_dir_and_file(g_get_home_dir(),
						".galeon/mimeTypes.xml");

	/* version doesn't really make sense, but... */
        doc = xmlNewDoc ("1.0");

	/* create and set the root node for the session */
        root_node = xmlNewDocNode (doc, NULL, "mimetypes", NULL);
        xmlDocSetRootElement (doc, root_node);

	/* iterate through all the windows */
	for (m = mime_types; m != NULL; m = g_list_next (m))
	{
		/* get this item */
		MimeItem *aMimeItem = (MimeItem *)(m->data);

		/* make a new XML node */
		mime_node = xmlNewDocNode (doc, NULL, "mimeitem", NULL);

		/* fill out fields */
		xmlSetProp (mime_node, "name", aMimeItem->name);
		snprintf (buffer, 5, "%d", aMimeItem->action);
		xmlSetProp (mime_node, "action", buffer);
		xmlSetProp (mime_node, "helper", aMimeItem->helperApp);
		snprintf (buffer, 3, "%d", aMimeItem->terminalHelper);
		xmlSetProp (mime_node, "helperNeedsTerminal", buffer);
		snprintf (buffer, 3, "%d", aMimeItem->urlHelper);
		xmlSetProp (mime_node, "helperTakesUrl", buffer);
		snprintf (buffer, 3, "%d", aMimeItem->alwaysUse);
		xmlSetProp (mime_node, "alwaysUse", buffer);

		xmlAddChild (root_node, mime_node);
	}

	/* save it all out to disk */

        xmlSaveFile (filename, doc);
	xmlFreeDoc (doc);
	g_free (filename);
}

/**
 * mime_db_shutdown: Clean up mime database memory structures
 */
void mime_db_shutdown (void)
{
	GList *m = NULL;
	for (m = mime_types; m != NULL; m = g_list_next (m))
	{
		mime_item_free ((MimeItem *)m->data);
	}
	g_list_free (mime_types);	
}

/**
 * mime_db_load: load a mime database into a new XML document
 */
void mime_db_load (void)
{
	xmlDocPtr doc;
	xmlNodePtr m;

	gchar *filename = g_concat_dir_and_file(g_get_home_dir(),
						".galeon/mimeTypes.xml");

	/* check the file exists */
	if (!(g_file_exists (filename)))
	{
		/* first time run, create database internally */
		mime_init_defaults ();
		g_free (filename);
		return;
	}

	/* load the file */
	doc = xmlParseFile (filename);
	g_free (filename);
	if (doc == NULL) 
	{
		g_warning ("unable to parse `%s', resetting "
			   "to defaults ", filename);
		mime_init_defaults ();
		return;
	}

	/* free up any existing list of MIME types */
	if (mime_types != NULL)
	{
		g_list_foreach (mime_types, (GFunc) mime_item_free, NULL);
		g_list_free (mime_types);
		mime_types = NULL;
	}

	/* iterate over mime types in document */
        for (m = doc->root->childs; m != NULL; m = m->next)
	{
		gchar *name, *helperApp;
		MimeItem *aMimeItem = g_new0 (MimeItem, 1);

		name = xmlGetProp (m, "name");
		aMimeItem->name = g_strdup (name);
		aMimeItem->action = xmlGetIntProp (m, "action");
		helperApp = xmlGetProp (m, "helper");
		aMimeItem->helperApp = g_strdup (helperApp);
		aMimeItem->terminalHelper = 
				xmlGetIntProp (m, "helperNeedsTerminal");
		aMimeItem->urlHelper = xmlGetIntProp (m, "helperTakesUrl");
		aMimeItem->alwaysUse = xmlGetIntProp (m, "alwaysUse");

		mime_types = g_list_append (mime_types, aMimeItem);

		if (name) xmlFree (name);
		if (helperApp) xmlFree (helperApp);
	}

	xmlFreeDoc (doc);
}
