#ifndef MAP_BASE_H
#define MAP_BASE_H

/**
	Template base class for implementing mapping on nodes.
	\param The first template parameter is the Graph class. The Graph
		must have an \emp node_maps member with \emp MapRegistry class.
	\param The second template parameter is the  type of the class.
	
*/


namespace hugo {
	template <typename G, typename K, typename KIt>
	class MapBase;
}

#include "map_registry.h"

namespace hugo {

	template <typename G, typename K, typename KIt>
	class MapBase {
	public:
		typedef G Graph;
		typedef MapRegistry<G, K, KIt> Registry;
		typedef K KeyType;
		typedef KIt KeyIt;
	
		friend class Registry;
		
		/** 
			Default constructor.
		*/	
		
		MapBase() : registry(0) {}

		/** 
			Simple constructor to register into a graph registry.
		*/
	
		MapBase(Registry& r) : registry(0) {
			registry->add(*this);
		}

		/** 
			Copy constructor with registering into the map.
		*/	
	
		MapBase(const MapBase& copy) : registry(0) {
			if (registry) {
				registry->add(*this);
			}
		} 
	
		/** 
			Assign operator.
		*/	

		const MapBase& operator=(const MapBase& copy) {
			if (registry) {
				registry->erase(*this);
			}
			registry = copy.registry;
			if (registry) {
				registry->add(*this);
			}
		}
	

		/** 
			Destructor.
		*/		

		virtual ~MapBase() {
			if (registry) {
				registry->erase(*this);
			}
		}
	
	protected:
		
		Registry* registry;

		int registry_index;
	
		/**
			Helper function to implement the default constructor in the subclasses.
		*/
	
		virtual void init(Graph& g) {

			for (KeyIt it(g); g.valid(it); g.next(it)) {
				add(it);
			}
		}
	
		/**
			Helper function to implement the destructor in the subclasses.
		*/
	
		virtual void destroy(Graph& g) {
			for (KeyIt it(g); g.valid(it); g.next(it)) {
				erase(it);
			}
		}
	
		/** 
			The add member function should be overloaded in the subclasses.
			\e Add extends the map with the new node.
		*/
	
		virtual void add(const KeyType&) = 0;
	
		/** 
			The erase member function should be overloaded in the subclasses.
			\e Erase removes the node from the map.
		*/
	
		virtual void erase(const KeyType&) = 0;
	
		/**
			Exception class to throw at unsupported operation.
		*/
	
		class NotSupportedOperationException {};

	};
	
}

#endif
