/* 
 *  Copyright (C) 2002 Ricardo Fernández Pascual
 *  Copyright (C) 2003 Marco Pesenti Gritti
 *  Copyright (c) 2003 Christian Persch
 *
 *  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.
 *
 *  $Id: bookmarks-epiphany.c,v 1.4 2004/03/30 21:33:05 crispin Exp $
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "bookmarks-epiphany.h"

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include <glib/gi18n.h>
#include <libgnome/gnome-util.h>

#include "gul-gobject-misc.h"
#include "gul-general.h"

#define NOT_IMPLEMENTED g_warning ("not implemented: " G_STRLOC);

struct _GbIOEpiphanyPrivate
{
};

/**
 * Private functions, only availble from this file
 */
static void		gb_io_epiphany_class_init		(GbIOEpiphanyClass *klass);
static void		gb_io_epiphany_init			(GbIOEpiphany *io);
static void		gb_io_epiphany_finalize			(GObject *object);
static GbBookmarkSet *	gb_io_epiphany_load_from_file		(GbIO *io, const gchar *filename);
static GbBookmarkSet *	gb_io_epiphany_load_from_string		(GbIO *io, const gchar *data);
static gboolean		gb_io_epiphany_save_to_file		(GbIO *io, GbBookmarkSet *set,
								 const gchar *filename);
static gboolean		gb_io_epiphany_save_to_string		(GbIO *io, GbBookmarkSet *set, gchar **data);
static gchar *		gb_io_epiphany_format_name 		(GbIO *io);
static GList *		gb_io_epiphany_extensions 		(GbIO *io);

/**
 * GbIOEpiphany object
 */

MAKE_GET_TYPE (gb_io_epiphany, "GbIOEpiphany", GbIOEpiphany, gb_io_epiphany_class_init, 
	       gb_io_epiphany_init, GB_TYPE_IO);

static void
gb_io_epiphany_class_init (GbIOEpiphanyClass *klass)
{
	GObjectClass *object_class = G_OBJECT_CLASS (klass);
	GbIOClass *gb_io_class = GB_IO_CLASS (klass);

	object_class->finalize = gb_io_epiphany_finalize;

	gb_io_class->gb_io_load_from_file = gb_io_epiphany_load_from_file;
	gb_io_class->gb_io_load_from_string = gb_io_epiphany_load_from_string;
	gb_io_class->gb_io_save_to_file = gb_io_epiphany_save_to_file;
	gb_io_class->gb_io_save_to_string = gb_io_epiphany_save_to_string;
	gb_io_class->gb_io_format_name = gb_io_epiphany_format_name;
	gb_io_class->gb_io_extensions = gb_io_epiphany_extensions;
}

static void 
gb_io_epiphany_init (GbIOEpiphany *io)
{
	io->priv = g_new0 (GbIOEpiphanyPrivate, 1);
}

static void
gb_io_epiphany_finalize (GObject *object)
{
	GbIOEpiphany *io = GB_IO_EPIPHANY (object);

	g_free (io->priv);
}

GbIOEpiphany *
gb_io_epiphany_new (void)
{
	return g_object_new (GB_TYPE_IO_EPIPHANY, NULL);
}

static void
parse_rdf_subjects (xmlNodePtr node,
		    GList **subjects)
{
	xmlChar *subject;

	subject = xmlNodeGetContent (node);

	if (subject)
	{
		*subjects = g_list_append (*subjects, subject);
	}
}

static GbBookmark *
bookmark_add (GbBookmarkSet *set,
	      const char *title,
	      const char *address,
	      const char *smartlink)
{
	GbSite *site;

	if (smartlink)
	{
		site = GB_SITE (gb_smart_site_new (set, title, address, smartlink));
	}
	else
	{
		site = gb_site_new (set, title, address);
	}

	return GB_BOOKMARK (site);
}

static int
find_folder (const GbBookmark *folder, const char *title)
{
	if (title == NULL)
	{
		return -1;
	}

	if (folder->name)
	{
		return strcmp (folder->name, title);
	}

	return 0;
}

static void
parse_rdf_item (GbBookmarkSet *set,
		GbFolder *root,
		GList **folders,
		xmlNodePtr node)
{
	xmlChar *title = NULL;
	xmlChar *link = NULL;
	xmlChar *smartlink = NULL;
	GList *subjects = NULL, *l;
	xmlNodePtr child;
	GbBookmark *bmk;

	child = node->children;

	while (child != NULL)
	{
		if (xmlStrEqual (child->name, "title"))
		{
			title = xmlNodeGetContent (child);
		}
		else if (xmlStrEqual (child->name, "link"))
		{
			link = xmlNodeGetContent (child);
		}
		else if (xmlStrEqual (child->name, "subject"))
		{
			parse_rdf_subjects (child, &subjects);
		}
		else if (xmlStrEqual (child->name, "smartlink"))
		{
			smartlink = xmlNodeGetContent (child);
		}

		child = child->next;
	}

	bmk = bookmark_add (set, title, link, smartlink);
	g_return_if_fail (bmk != NULL);

	for (l = subjects; l != NULL; l = l->next)
	{
		const char *title = (char *) l->data;
		GbFolder *folder;
		GList *item;

		item = g_list_find_custom (*folders, title, (GCompareFunc) find_folder);

		if (item)
		{
			folder = GB_FOLDER (item->data);
		}
		else
		{
			/* create folder from subject */
			folder = gb_folder_new (set, title);
			gb_folder_add_child (root, GB_BOOKMARK (folder), -1);

			*folders = g_list_prepend (*folders, folder);
		}

		gb_bookmark_add_alias_under (bmk, folder);
	}

	if (subjects == NULL)
	{
		/* "Uncategorised" bookmark, add to root folder */
		gb_folder_add_child (root, bmk, -1);
	}

	xmlFree (title);
	xmlFree (link);
	xmlFree (smartlink);

	g_list_foreach (subjects, (GFunc) xmlFree, NULL);
	g_list_free (subjects);
}


static GbBookmarkSet * 
rdf_read (xmlDocPtr doc) 
{
	GbBookmarkSet *set;
	GbFolder *import_folder;
	xmlNodePtr root, child;
	GList *folders = NULL;

	root = xmlDocGetRootElement (doc);

	set = gb_bookmark_set_new ();
	import_folder = gb_folder_new (set, _("Epiphany bookmarks"));
	gb_bookmark_set_set_root (set, import_folder);

	for (child = root->children; child != NULL; child = child->next)
        {
                if (xmlStrEqual (child->name, "item"))
                {
                        parse_rdf_item (set, import_folder, &folders, child);
                }
        }

	gb_bookmark_set_resolve_aliases (set);
	gb_folder_sort (import_folder, TRUE, TRUE);

	if (folders)
	{
		g_list_free (folders);
	}

	g_object_unref (G_OBJECT (import_folder));

	return set;
}

GbBookmarkSet *
gb_io_epiphany_load_from_file (GbIO *io, const gchar *filename)
{
	GbBookmarkSet *set = NULL;
	xmlDocPtr doc;
	
	if (g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE)
	{
		/* no bookmarks, ERROR */
		return NULL;
	}

	doc = xmlParseFile (filename);

	if (doc)
	{
		set = rdf_read (doc);
	}
	else
	{
		g_warning ("unable to parse bookmarks file: %s", filename);
	}

	xmlFreeDoc (doc);

	return set;
}

GbBookmarkSet *
gb_io_epiphany_load_from_string (GbIO *io, const gchar *data)
{
	GbBookmarkSet *set = NULL;
	xmlDocPtr doc;
	
	if (data == NULL)
	{
		/* no bookmarks, ERROR */
		return NULL;
	}

	doc = xmlParseMemory (data, strlen (data));

	if (doc)
	{
		set = rdf_read (doc);
	}
	else
	{
		g_warning ("unable to parse bookmarks data: %s", data);
	}

	xmlFreeDoc (doc);

	return set;
}

gboolean
gb_io_epiphany_save_to_file (GbIO *io, GbBookmarkSet *set,
			     const gchar *filename)
{
	g_return_val_if_fail (filename != NULL, FALSE);

	NOT_IMPLEMENTED;
	return FALSE;
}

gboolean
gb_io_epiphany_save_to_string (GbIO *io, GbBookmarkSet *set, gchar **data)
{
	NOT_IMPLEMENTED;
	return FALSE;
}

gchar *
gb_io_epiphany_format_name (GbIO *io)
{
	return g_strdup (_("Epiphany RDF bookmarks format"));
}

GList *
gb_io_epiphany_extensions (GbIO *io)
{
	static gchar *extensions[] = { "rdf", NULL };
	GList *l = NULL;
	int i;
	for (i = 0; extensions[i] != NULL; i++)
	{
		l = g_list_append (l, g_strdup (extensions[i]));
	}
	return l;
}
