///---------------------------------------------------------------------
///
/// Append R*-Tree visiting facilities.
/// Code inspired (nearly copied) from example file of Dustin Spicuzza <dustin@virtualroadside.com>
///
/// Modification by Christophe Leblanc.
/// Date: 20/06/2013.
 	
#ifndef TOMOPROCESS_RSTARTREE_VISITOR_H
#define TOMOPROCESS_RSTARTREE_VISITOR_H
 	
#include "RStarTree.h"
#include <list>
 	
namespace rstartree {
  	
/**
	\class Visitor
	\brief Implementation of a generic RTree visitor with an R* index.
	@tparam LeafType		type of leaves stored in the tree
	@tparam dimensions  	number of dimensions the bounding boxes are described in
	@tparam	min_child_items m, in the range 2 <= m < M
	@tparam max_child_items M, in the range 2 <= m < M
	@tparam	RemoveLeaf 		A functor used to remove leaves from the tree
*/
template<typename LeafTypeT,
  std::size_t dimensions, std::size_t min_child_items, std::size_t max_child_items>
class Visitor
{
public:
  typedef LeafTypeT LeafType;
  typedef RStarTree<LeafType, dimensions, min_child_items, max_child_items> RTreeType;
  typedef std::pair< LeafType*,
    const typename RTreeType::BoundingBox* > PairType;
  typedef std::list<PairType> DataType;
 	
  std::size_t count;
  bool ContinueVisiting;
 	
  // first: pointer to the visited items.
  // second: pointer to the bounding boxes of the visited items.
  DataType data;
  	
  Visitor(): count(0), ContinueVisiting(true) {}
 	
  Visitor(const Visitor &rhs): count(rhs.count), 
    ContinueVisiting(rhs.ContinueVisiting),
    data(rhs.data) {}
  	
  ~Visitor() {}
  	
  Visitor& operator=(const Visitor &rhs)
  {
    if(this != &rhs) {
      count = rhs.count;
      ContinueVisiting = rhs.ContinueVisiting;
      data = rhs.data; // Copy pointers.
    }
 	
    return (*this);
  }
 	
  void operator()(typename RTreeType::Leaf * leaf)
  {
    PairType pair(&(leaf->leaf), &(leaf->bound)); // Get read access to visited leaves	
						  // and to bounding boxes of visited leaves.
    data.push_back(pair);
    count++;
  }
  	
  std::size_t size() const { return count; }
 	
  DataType& Data() { return data; }
  const DataType& Data() const { return data; }
};
 	
} // namespace rstartree
 	
#endif // TOMOPROCESS_RSTARTREE_VISITOR_H
