#include <lemon/list_graph.h>
#include <lemon/maps.h>
#include <list>

using namespace lemon;

template<class GR>
class Reader 
{
  
public:
  typedef GR Graph;
  typedef typename Graph::Node Node;
  typedef typename Graph::Edge Edge;
    
  ///A beolvasando ertekek tipusa.

  ///Ebben gyakorlatilag egy stringet tarolunk.
  ///Tovabba ez egy olyan tipus, amitol elvarjuk, hogy konvertalodjon
  ///a beolvasando mapok Value-jara.
  class InputValue 
  {
  public:
    operator int()    const { return 0; }
    operator double() const { return 0; }
  };

  ///Ez adja a mapok kozos interface-et.
  class WrapEdgeMapBase 
  {
  public:
    virtual void set(Edge n,const InputValue &v) = 0;
    virtual ~WrapEdgeMapBase() {}
  };

  ///Ez meg becsomagol egy mapot a kozos formara.
  template<class M>
  class WrapEdgeMap : public WrapEdgeMapBase
  {
    M &map;
    
  public:
    WrapEdgeMap(M &m) : map(m) {}
    void set(Edge n,const InputValue &v) {map.set(n,v);}
  };

  ///Ebben a strukturaban adunk meg egy feltoltendo mapot.
  struct EdgeMapDesc 
  {
    std::string name;
    int column;
    WrapEdgeMapBase *map;
    
    template<class M> EdgeMapDesc(char *n,M &m) : name(n), map(&m) {}
    ~EdgeMapDesc() {}    
  };
  
  ///Itt vannak felsorolva a feltoltendo mapok
  std::list<EdgeMapDesc> EdgeMaps;

  ///Ezzel lehet egy mapot hozzaadni a feltoltendok listajahoz.
  template<class M> void addEdgeMap(char *name,M &map)
  {
    EdgeMaps.push_back(EdgeMapDesc(name,*(new WrapEdgeMap<M>(map))));
  }
  
  ///Ez meg kiuriti a map-listat.
  void removeEdgeMaps() 
  {
    while(EdgeMaps.begin()!=EdgeMaps.end()) {
      //Ez igy OK?:
      delete EdgeMaps.begin()->map;
      EdgeMaps.pop_front();
    }
  }
  
  //Esetleg stream a file-nev helyett...
  Reader(char *file,Graph &G)
  {
     removeEdgeMaps();
  }
  
  ///Ez inditja a beolvasast.
  void read() 
  {
    //Ez olvassa be/vegig a file-t.
  }
  
  ~Reader() 
  {
    //Ez kell!!!
    removeEdgeMaps();
  }
  
};

class SumMap : public MapBase<ListGraph::Edge,double>
{
  double sum;
public:
  SumMap() : sum(0) {}
  void set(ListGraph::Edge e,double d) 
  {
    sum+=d;
  }
  double getSum() { return sum; }
};

int main() 
{
  ListGraph g; //Kis g!!!
  ListGraph::EdgeMap<double> cost(g);
  ListGraph::EdgeMap<int> channels(g);
  
  SumMap sum_cost; //Ez egy sajat "custom" irhato map
  
  Reader<ListGraph> r("file_name.lgf",g);
  r.addEdgeMap("cost",cost);
  r.addEdgeMap("channels",channels);
  r.addEdgeMap("cost",sum_cost);
  r.read();
}
