#ifndef EXAMPLE_NODE_STORE_H
#define EXAMPLE_NODE_STORE_H

#include <glibmm/tree.h>

namespace Example
{

  template < typename T > class NodeStore :
    public Glib::Object, 
    public Gtk::TreeModel,
    public Gtk::TreeDragSource,
    public Gtk::TreeDragDest,
    public Glib::Tree< T >
  {
  protected:
    NodeStore(T data_root) :
      Glib::Object(),
      Gtk::TreeModel(),
      Glib::Tree< T >(data_root)
    {
    }

    virtual ~NodeStore()
    {
    }
    
    Gtk::TreeModel::iterator iterator(const Glib::Tree< T > &node) const
    {
      Gtk::TreeModel::iterator iter;

      iter.gobj()->user_data = const_cast< Glib::Tree< T > * >(&node);

      return iter;
    }

    const Glib::Tree< T > *get_node_from_iter(const Gtk::TreeModel::iterator iter) const
    {
      return static_cast<const Glib::Tree< T > * >(iter.gobj()->user_data);
    }

    bool iter_nth_child(const Gtk::TreeModel::iterator& parent, int n, Gtk::TreeModel::iterator& iter) const
    {
      const Glib::Tree< T > *node;
    
      node = get_node_from_iter(parent);
      if (!node)
        return false;
    
      node = node->nth_child(n);
      if (!node)
        return false;

      iter = iterator(*node);

      return true;
    }


    bool get_iter(const Gtk::TreeModel::Path &path, Gtk::TreeModel::iterator &iter) const
    {
      Gtk::TreeModel::iterator node_parent = iterator(*this);
      Glib::ArrayHandle<int> indices = path.get_indices();

      for (Glib::ArrayHandle<int>::const_iterator i = indices.begin(); i != indices.end(); ++i)
      {
        if (!iter_nth_child(node_parent, *i, node_parent))
    	    return false;

      }

      iter = node_parent;
    
      return true;
    }


    virtual Gtk::TreeModelFlags get_flags_vfunc() const
    {
      return Gtk::TreeModelFlags(0);
    }


    virtual bool get_iter_vfunc(const Gtk::TreeModel::Path &path, Gtk::TreeModel::iterator &iter) const
    {
      return get_iter(path, iter);
    }


    virtual bool iter_next_vfunc(const Gtk::TreeModel::iterator &iter, Gtk::TreeModel::iterator &iter_next) const
    {
      const Glib::Tree< T > *node = get_node_from_iter(iter);

      if (!node)
        return false;

      node = node->next_sibling();
      if (!node)
        return false;

      iter_next = iterator(*node);

      return true;
    }


    virtual bool iter_children_vfunc(const Gtk::TreeModel::iterator &parent, Gtk::TreeModel::iterator &iter) const
    {
      const Glib::Tree< T > *node;
      
      node = get_node_from_iter(parent);
      if (!node || node->is_leaf())
        return false;

      iter = iterator(*node->first_child());

      return true;
    }


    virtual bool iter_has_child_vfunc(const Gtk::TreeModel::iterator& iter) const
    {
      const Glib::Tree< T > *node = get_node_from_iter(iter);

      return (node && !node->is_leaf());
    }


    virtual int iter_n_children_vfunc(const Gtk::TreeModel::iterator& iter) const
    {
      const Glib::Tree< T > *node = get_node_from_iter(iter);

      return node ? node->child_count() : 0;
    }


    virtual int iter_n_root_children_vfunc() const
    {
      return this->child_count();
    }


    virtual bool iter_nth_child_vfunc(const Gtk::TreeModel::iterator& parent, int n, Gtk::TreeModel::iterator& iter) const
    {
      const Glib::Tree< T > *node;

      node = get_node_from_iter(parent);
      if (!node || node->is_leaf())
        return false;

      node = node->nth_child(n);
      if (!node)
        return false;

      iter = iterator(*node);

      return true;
    }


    virtual bool iter_nth_root_child_vfunc(int n, Gtk::TreeModel::iterator& iter) const
    {
      const Glib::Tree< T > *node;

      node = this->nth_child(n);
      if (!node)
        return false;

      iter = iterator(*node);

      return true;
    }


    virtual bool iter_parent_vfunc(const Gtk::TreeModel::iterator& child, Gtk::TreeModel::iterator& iter) const
    {
      const Glib::Tree< T > *node;

      node = get_node_from_iter(child);
      if (!node)
        return false;

      node = node->get_parent();
      if (!node)
        return false;

      iter = iterator(*node);

      return true;
    }


    virtual Gtk::TreeModel::Path get_path_vfunc(const Gtk::TreeModel::iterator &iter) const
    {
      Gtk::TreeModel::Path path;

      for (const Glib::Tree< T > *node = get_node_from_iter(iter);
           node;
           node = node->get_parent())
        path.push_back(position_of(*node->get_parent()));
      
      return path;
    }
  };
}


#endif

