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

/*
 *  Copyright (C) 2003 Hiroyuki Ikezoe
 *  Copyright (C) 2003 Takuro Ashie
 *
 *  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: kz-proxy-folder.c 1930 2005-02-13 13:20:37Z ikezoe $
 */

#include "kz-proxy-folder.h"

#include <glib/gi18n.h>
#include "gobject-utils.h"

typedef struct _KzProxyFolderPriv KzProxyFolderPriv;
struct _KzProxyFolderPriv
{
	KzBookmark *bookmark;
};

#define KZ_PROXY_FOLDER_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), KZ_TYPE_PROXY_FOLDER, KzProxyFolderPriv))

enum {
	PROP_0,
	PROP_KZ_BOOKMARK
};

static void     kz_proxy_folder_class_init   (KzProxyFolderClass *klass);
static void     kz_proxy_folder_init         (KzProxyFolder      *proxy_folder);
static GObject *kz_proxy_folder_constructor  (GType type,
					      guint n_props,
					      GObjectConstructParam *props);
static void     kz_proxy_folder_dispose      (GObject            *object);

static void     kz_proxy_folder_set_property (GObject            *object,
					      guint               prop_id,
					      const GValue       *value,
					      GParamSpec         *pspec);
static void     kz_proxy_folder_get_property (GObject            *object,
					      guint               prop_id,
					      GValue             *value,
					      GParamSpec         *pspec);

static void     cb_folder_insert_child	     (KzBookmark    *folder,
					      KzBookmark    *child,
					      KzBookmark    *sibling,
					      KzProxyFolder *proxy);
static void     cb_folder_remove_child       (KzBookmark    *folder,
					      KzBookmark    *child,
					      KzProxyFolder *proxy);

static KzBookmarkClass *parent_class = NULL;


KZ_OBJECT_GET_TYPE(kz_proxy_folder, "KzProxyFolder", KzProxyFolder,
		   kz_proxy_folder_class_init, kz_proxy_folder_init,
		   KZ_TYPE_BOOKMARK)


static void
kz_proxy_folder_class_init (KzProxyFolderClass *klass)
{
	GObjectClass *object_class;

	parent_class = g_type_class_peek_parent (klass);
	object_class = (GObjectClass *) klass;

	object_class->constructor  = kz_proxy_folder_constructor;
	object_class->dispose      = kz_proxy_folder_dispose;
	object_class->set_property = kz_proxy_folder_set_property;
	object_class->get_property = kz_proxy_folder_get_property;
	g_object_class_install_property
		(object_class,
		 PROP_KZ_BOOKMARK,
		 g_param_spec_object ("kz-bookmark",
				      _("KzBookmark"),
				      _("The Bookmark object"),
				      KZ_TYPE_BOOKMARK,
				      G_PARAM_READWRITE |
				      G_PARAM_CONSTRUCT_ONLY));
	g_type_class_add_private (klass, sizeof(KzProxyFolderPriv));
}


static void
kz_proxy_folder_init (KzProxyFolder *proxy)
{
	KzProxyFolderPriv *priv = KZ_PROXY_FOLDER_GET_PRIVATE(proxy);

	priv->bookmark = NULL;
}


static KzBookmark *
create_current_page_bookmark (KzBookmark *tab)
{
	KzBookmark *cur_page;
	gint cur_pos;
	GList *pages;
	KzBookmark *new;

	cur_pos = kz_bookmark_get_current(tab);

	pages = kz_bookmark_get_children(tab);
	cur_page = KZ_BOOKMARK(g_list_nth_data(pages, cur_pos));
	g_list_free(pages);

	new = kz_bookmark_new_with_attrs(kz_bookmark_get_title(cur_page),
					 kz_bookmark_get_link(cur_page),
					 NULL);

	return new;
}


static void
create_proxy_folder (KzProxyFolder *proxy, KzBookmark *tabs)
{
	GList *children, *node;
	
	children = kz_bookmark_get_children(tabs);
	
	for (node = children; node; node = g_list_next(node))
	{
		KzBookmark *cur_page;
		cur_page = create_current_page_bookmark(KZ_BOOKMARK(node->data));

		kz_bookmark_append(KZ_BOOKMARK(proxy), cur_page);
		g_object_unref(cur_page);
	}

	g_list_free(children);
}


static GObject*
kz_proxy_folder_constructor (GType type,
			     guint n_props,
			     GObjectConstructParam *props)
{
	GObject *object;
	GObjectClass *klass = G_OBJECT_CLASS(parent_class);
	KzProxyFolder *proxy;
	KzProxyFolderPriv *priv;

	object = klass->constructor(type, n_props, props);
	proxy = KZ_PROXY_FOLDER(object);
	priv = KZ_PROXY_FOLDER_GET_PRIVATE(object);

	/* set signals */
	g_signal_connect(priv->bookmark, "insert-child",
			       G_CALLBACK(cb_folder_insert_child),
			       proxy);
	g_signal_connect(priv->bookmark, "remove-child",
			       G_CALLBACK(cb_folder_remove_child),
			       proxy);

	return object;
}


static void
kz_proxy_folder_dispose (GObject *object)
{
	KzProxyFolder *proxy = KZ_PROXY_FOLDER(object);
	KzProxyFolderPriv *priv = KZ_PROXY_FOLDER_GET_PRIVATE(object);

	if (priv->bookmark)
	{
		g_signal_handlers_disconnect_by_func
			(priv->bookmark,
			 G_CALLBACK(cb_folder_insert_child),
			 proxy);
		g_signal_handlers_disconnect_by_func
			(priv->bookmark,
			 G_CALLBACK(cb_folder_remove_child),
			 proxy);
		g_object_unref(priv->bookmark);
	}
	priv->bookmark = NULL;

	if (G_OBJECT_CLASS (parent_class)->dispose)
		G_OBJECT_CLASS (parent_class)->dispose(object);
}


static void
kz_proxy_folder_set_property (GObject *object,
			      guint prop_id,
			      const GValue *value,
			      GParamSpec *pspec)
{
	KzProxyFolderPriv *priv = KZ_PROXY_FOLDER_GET_PRIVATE(object);
  
	switch (prop_id)
	{
	case PROP_KZ_BOOKMARK:
		priv->bookmark = g_object_ref(g_value_get_object(value));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}


static void 
kz_proxy_folder_get_property (GObject *object,
			      guint prop_id,
			      GValue *value,
			      GParamSpec *pspec)
{
	KzProxyFolderPriv *priv = KZ_PROXY_FOLDER_GET_PRIVATE(object);

	switch (prop_id)
	{
	case PROP_KZ_BOOKMARK:
		g_value_set_object(value, priv->bookmark);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}


KzBookmark *
kz_proxy_folder_new (KzBookmark *bookmark)
{
	KzBookmark *proxy;
	proxy = KZ_BOOKMARK(g_object_new(KZ_TYPE_PROXY_FOLDER,
			    "type",        KZ_BOOKMARK_PURE_FOLDER,
			    "title",       _("ProxyFolder"),
			    "kz-bookmark", bookmark,
			    NULL));

	create_proxy_folder(KZ_PROXY_FOLDER(proxy), bookmark);
	return proxy;
}


static void
cb_folder_insert_child (KzBookmark *folder,
			KzBookmark *child, KzBookmark *sibling,
			KzProxyFolder *proxy)
{
	KzBookmark *new;
	KzProxyFolderPriv *priv = KZ_PROXY_FOLDER_GET_PRIVATE(proxy);
	new = create_current_page_bookmark(child);

	if (sibling)
	{
		GList *list;
		gint index;

		list = kz_bookmark_get_children(priv->bookmark);
		index = g_list_index(list, sibling);
		if (index >= 0)
		{
			GList *children;
			KzBookmark *sib;

			children = kz_bookmark_get_children(KZ_BOOKMARK(proxy));
			sib = KZ_BOOKMARK(g_list_nth_data(children, index));
			kz_bookmark_insert_before(KZ_BOOKMARK(proxy),
						  new, 
					          sib);
			g_list_free(children);
		}
		g_list_free(list);
	}
	else
	{
		kz_bookmark_prepend(KZ_BOOKMARK(proxy), new);
	}
	g_object_unref(new);
}


static void
cb_folder_remove_child (KzBookmark *folder,
			KzBookmark *child, 
			KzProxyFolder *proxy) 
{
	GList *list;
	gint index;
	KzProxyFolderPriv *priv = KZ_PROXY_FOLDER_GET_PRIVATE(proxy);

	list = kz_bookmark_get_children(priv->bookmark);
	index = g_list_index(list, child);
	if (index >= 0)
	{
		GList *children;
		KzBookmark *remove;

		children = kz_bookmark_get_children(KZ_BOOKMARK(proxy));
		remove = KZ_BOOKMARK(g_list_nth_data(children, index));
		kz_bookmark_remove(KZ_BOOKMARK(proxy), remove);
		g_list_free(children);
	}
	g_list_free(list);
}


KzBookmark *
kz_proxy_folder_get_original_bookmark (KzProxyFolder *proxy,
				       KzBookmark *bookmark)
{
	GList *list;
	gint index;
	KzBookmark *orig = NULL;
	KzProxyFolderPriv *priv = KZ_PROXY_FOLDER_GET_PRIVATE(proxy);

	list = kz_bookmark_get_children(KZ_BOOKMARK(proxy));
	index = g_list_index(list, bookmark);

	if (index >= 0)
	{
		GList *children;
		children = kz_bookmark_get_children(priv->bookmark);
		orig = KZ_BOOKMARK(g_list_nth_data(children, index));
		g_list_free(children);
	}
	g_list_free(list);

	return orig;
}

KzBookmark *
kz_proxy_folder_get_original_bookmark_from_index (KzProxyFolder *proxy,
				                  gint index)
{
	GList *list;
	KzBookmark *orig = NULL;
	KzProxyFolderPriv *priv = KZ_PROXY_FOLDER_GET_PRIVATE(proxy);

	list = kz_bookmark_get_children(priv->bookmark);
	orig = KZ_BOOKMARK(g_list_nth_data(list, index));
	g_list_free(list);

	return orig;
}

