// -*- c++ -*-
#ifndef SYM_MAP_FACTORY_H
#define SYM_MAP_FACTORY_H

namespace hugo {

  template <typename Graph, typename Edge, typename EdgeIt>
  class SymEdgeIt : public EdgeIt {
  public:

    SymEdgeIt() 
      : EdgeIt() {}

    SymEdgeIt(const Graph& graph) 
      : EdgeIt(graph) {
      while ( n != -1 && (n & 1)) {
	EdgeIt::operator++();
      }
    }

    SymEdgeIt(Invalid invalid) 
      : EdgeIt(invalid) {}

    SymEdgeIt(const Graph& graph, Edge edge)
      : EdgeIt(graph, edge) {}

    SymEdgeIt& operator++() {
      EdgeIt::operator++();
      while ( n != -1 && (n & 1)) {
	EdgeIt::operator++();
      }
      return *this;
    }
  };

  template <typename MapRegistry, template <typename> class MapFactory>
  class SymMapFactory {

  public:
		
    typedef typename MapRegistry::Graph Graph;
    typedef typename MapRegistry::KeyType KeyType;
    typedef typename MapRegistry::KeyIt KeyIt;

    typedef typename MapRegistry::MapBase MapBase;

    template <typename V>
    class Map : public MapFactory<MapRegistry>::template Map<V> {

      typedef typename MapFactory<MapRegistry>::template Map<V> MapImpl;
    public:

      typedef V Value;

      Map() : MapImpl() {}

      Map(const Graph& g, MapRegistry& r) : MapImpl(g, r) {}

      Map(const Graph& g, MapRegistry& r, const Value& v) 
	: MapImpl(g, r, v) {}

      Map(const Map& copy) : MapImpl(static_cast<const MapImpl&>(copy)) {}

      template <typename CMap> Map(const CMap& copy) : MapImpl(copy) {}

      Map& operator=(const Map& copy) {
	MapImpl::operator=(static_cast<const MapImpl&>(copy));
	return *this;
      }

      template <typename CMap> Map& operator=(const CMap& copy) {
	MapImpl::operator=(copy);
	return *this;
      }
   
      Value& operator[](const KeyType& key) {
	int id = MapBase::getGraph()->id(key);	
	return MapImpl::operator[](id >> 1);
      } 
		
      const Value& operator[](const KeyType& key) const {
	int id = MapBase::getGraph()->id(key);
	return MapImpl::operator[](id >> 1);
      }
	
      const Value& get(const KeyType& key) const {
	int id = MapBase::getGraph()->id(key);
	return MapImpl::operator[](id >> 1);
      } 
		
      void set(const KeyType& key, const Value& val) {
	int id = MapBase::getGraph()->id(key);
	MapImpl::operator[](id >> 1) = val;
      }
		
      void add(const KeyType& key) {
	int id = MapBase::getGraph()->id(key);
	if (id & 1) return;
	MapImpl::add(key);
      }
		
      void erase(const KeyType& key) {
	int id = MapBase::getGraph()->id(key);
	if (id & 1) return;
	MapImpl::add(key);
      }


    };  
  };
}
#endif
