/*
 *  Copyright (C) 2002  Ricardo Fernández Pascual
 *
 *  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.
 */

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

#include "bookmarks-iterator.h"
#include "gul-gobject-misc.h"

/**
 * Private data
 */
struct _GbIteratorPrivate {
	gboolean recursive;
	GbIterator *current_item_iterator;
	GbBookmark *next_item;
};

/**
 * Private functions, only availble from this file
 */
static void		gb_iterator_class_init		(GbIteratorClass *klass);
static void		gb_iterator_init		(GbIterator *i);
static void		gb_iterator_finalize_impl	(GObject *o);
static void		gb_iterator_set_current_folder	(GbIterator *i, GbFolder *f);

static gpointer g_object_class;

/**
 * Iterator object
 */

MAKE_GET_TYPE (gb_iterator, "GbIterator", GbIterator, gb_iterator_class_init, 
	       gb_iterator_init, G_TYPE_OBJECT);

static void
gb_iterator_class_init (GbIteratorClass *klass)
{
	G_OBJECT_CLASS (klass)->finalize = gb_iterator_finalize_impl;
	g_object_class = g_type_class_peek_parent (klass);
}

static void 
gb_iterator_init (GbIterator *e)
{
	GbIteratorPrivate *p = g_new0 (GbIteratorPrivate, 1);
	e->priv = p;
}

static void
gb_iterator_finalize_impl (GObject *o)
{
	GbIterator *e = GB_ITERATOR (o);

	gb_iterator_set_current_folder (e, NULL);
	g_free (e->priv);

	G_OBJECT_CLASS (g_object_class)->finalize (o);
}

GbIterator *
gb_iterator_new (GbBookmarkSet *set)
{
	GbIterator *ret = g_object_new (GB_TYPE_ITERATOR, NULL);
	ret->priv->next_item = GB_BOOKMARK (set->root);
	g_object_ref (G_OBJECT (ret->priv->next_item));
	ret->priv->recursive = TRUE;
	return ret;
}

GbIterator *
gb_iterator_new_folder (GbFolder *f, gboolean recursive)
{
	GbIterator *ret = g_object_new (GB_TYPE_ITERATOR, NULL);
	gb_iterator_set_current_folder (ret, f);
	ret->priv->recursive = recursive;
	return ret;
}

static void
gb_iterator_set_current_folder (GbIterator *i, GbFolder *f)
{
	GbIteratorPrivate *p = i->priv;
	if (p->current_item_iterator)
	{
		g_object_unref (G_OBJECT (p->current_item_iterator));
		p->current_item_iterator = NULL;
	}
	if (p->next_item)
	{
		g_object_unref (G_OBJECT (p->next_item));
		p->next_item = NULL;
	}
	if (f && !gb_bookmark_is_alias (f) && f->child)
	{
		g_object_ref (G_OBJECT (f->child));
		p->next_item = f->child;
		p->current_item_iterator = NULL;
	}
}

GbBookmark *
gb_iterator_next (GbIterator *i)
{
	GbIteratorPrivate *p = i->priv;
	GbBookmark *ret;
	if (p->current_item_iterator)
	{
		ret = gb_iterator_next (p->current_item_iterator);
		if (!gb_iterator_has_next (p->current_item_iterator))
		{
			g_object_unref (G_OBJECT (p->current_item_iterator));
			p->current_item_iterator = NULL;
		}
	}
	else
	{
		ret = p->next_item;
		if (ret)
		{
			g_object_unref (G_OBJECT (ret));
			p->next_item = ret->next;
			if (p->next_item)
			{
				g_object_ref (G_OBJECT (p->next_item));
			}
			if (p->recursive && GB_IS_FOLDER (ret) && !gb_bookmark_is_alias (ret) && GB_FOLDER (ret)->child)
			{
				p->current_item_iterator = gb_iterator_new_folder (GB_FOLDER (ret), TRUE);
			}
		}
	}
	return ret;
}

gboolean 
gb_iterator_has_next (GbIterator *i)
{
	GbIteratorPrivate *p = i->priv;
	return p->next_item || p->current_item_iterator;
}



