#include <iostream>
#include <string>

/// Beolvaso osztaly terve:

// beolvaso es wrappelo bazis osztaly
class MapReader {
public:
  virtual void read(typename Map::Key& key, istream& is) = 0;
};

// a default beolvaso osztaly egy maphez
// elboldogul olyan mappel is, amelyben valamilyen specialis tipus van
template <typename _Map>
class DefaultReader : public MapReader {
public:
  typedef _Map Map;

  DefaultReader(Map& _map) : map(_map) {}

  virtual void read(typename Map::Key& key, istream& is) {
    typename Map::Value val;
    is >> val;
    map.set(key, val);
  }
private:
  Map& map;
};

// egy adott tipusu elemet beolvas, de nem irja mapbe
template <typename _Type>
class SkipReader : public MapReader {
public:

  virtual void read(typename Map::Key&, istream& is) {
    _Type val;
    is >> val;
  }
};

// majd olyan stringeket lehet olvasni, ami idezojelek kozott van
template <typename _Map>
class QuotedStringReader {
public:
  typedef _Map Map;

  QuotedStringReader(Map& _map) : map(_map) {}

  virtual void read(typename Map::Key&, istream& is) {
    char c;
    is >> c;
  }
  
};


// a beolvaso
template <typename _Graph, template <typename> class _SkipReader = SkipReader<std::string> >
class GraphReader {

  GraphReader(istream& _is) : is(_is) {}

  template <typename _Map, typename _Reader = DefaultReader<_Map> >
  void readMap(std::string& name, _Map& _map) {
    readers.push_back(_Reader(_map));
  }

  template <_Type, typename _Reader = SkipReader<_Map> >
  void skipMap(std::string& name) {
    readers.push_back(_Reader());
  }

  void read() {    
    ...
    vector<int> index;
    // egy sor olvasasa
    for (int i = 0; i < index.size(); ++i) {
      if (index[i] != -1) {
	readers[index[i]].read(item, is);
      } else {
	_SkipReader().read(item, is);
      }
    }
    ...
  }


private:
  istream& is;
  vector<MapReader> readers;
};

// Ennek az implementacionak az elonye:
//  - altalanosabban mukodik a beolvasas
//  - konnyebb specialis beolvasasokat megvalositani
//  - ugyanolyan tipusu maphez ket kulonbozo beolvasasi modszert is alkalmazhatunk
//  - Megengedi, whitespace-t tartalmazo stringek beolvasasat is (?)

// Hatranya
//  - Ha whitespace-t hasznalunk egy mapben, de nem olvassuk ki, akkor meg kell
//    hivni a skipMap fuggvenyt az aktualis tipussal /a ws-eket ezt ellenjavalhatjuk a doksiban/

// Fejlesztesi lehetoseg:
// A GraphReader osztalynak nem a SkipReader lenne a parametere, hanem a kovetkezo tipusu osztaly:

class TypeReaderTraits {
public:
  class DefaultSkipReader {
    ...
  };

  template <typename Map>
  class MapReader {
    ...
  };

  template <typename Type>
  class SkipReader {
    ...
  };
};

// Ezt le lehetne cserelni peldaul DelimetedReaderTraits-re cserelni, amivel be lehetne spacekkel, vagy
// mas elvalasztojelekkel generalt file-t olvasni.  

// Kerdes
// Ugy ertelmeztem, hogy fontos az hogy kozos beolvaso interface legyen a kulonbozo
// tipusu beolvasasokhoz/file, adatbazis.../.
// Szerintem ez annyira nem fontos, mivel sem szarmaztatott viszonyban nem allnak
// a beolvaso interfacek, es annak sem latom ertelmet, hogy template parameter legyen
// a beolvaso osztaly. 
// Ezert szerintem nem kell kozos interfacce!
//
// Azonban celszeru kozel azonos szintaktikat kialakitani a beolvasokhoz,
// hogy egyszeru legyen hasznalni.
