//: C10:BeeAndFlowers.cpp
// Z knihy "Myslíme v jazyce C++, část 2" od Bruce Eckela a Chucka Allisona.
// (c) 1995-2004 MindView, Inc. Všechna práva vyhrazena.
// Přečtěte si podmínky používání zdrojových kódů umístěné v souboru 
// 'Licence.txt' dodávaném spolu s balíčkem kódu dostupným na www.MindView.net.
// Demonstrace vzoru Návštěvník.
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
#include "../purge.h"
using namespace std;

class Gladiola;
class Narciska;
class Chryzantema;

class Navstevnik {
public:
  virtual void navstivit(Gladiola* f) = 0;
  virtual void navstivit(Narciska* f) = 0;
  virtual void navstivit(Chryzantema* f) = 0;
  virtual ~Navstevnik() {}
};

class Kvetina {
public:
  virtual void prijmout(Navstevnik&) = 0;
  virtual ~Kvetina() {}
};

class Gladiola : public Kvetina {
public:
  virtual void prijmout(Navstevnik& v) {
    v.navstivit(this);
  }
};

class Narciska : public Kvetina {
public:
  virtual void prijmout(Navstevnik& v) {
    v.navstivit(this);
  }
};

class Chryzantema : public Kvetina {
public:
  virtual void prijmout(Navstevnik& v) {
    v.navstivit(this);
  }
};

// Přidat schopnost vytvořit řetězec
class StringVal : public Navstevnik {
  string s;
public:
  operator const string&() { return s; }
  virtual void navstivit(Gladiola*) {
    s = "Gladiola";
  }
  virtual void navstivit(Narciska*) {
    s = "Narciska";
  }
  virtual void navstivit(Chryzantema*) {
    s = "Chryzantéma";
  }
};

// Přidat schopnost zajistit "včelí" aktivity:
class Vcela : public Navstevnik {
public:
  virtual void navstivit(Gladiola*) {
    cout << "Včela a Gladiola" << endl;
  }
  virtual void navstivit(Narciska*) {
    cout << "Včela a Narciska" << endl;
  }
  virtual void navstivit(Chryzantema*) {
    cout << "Včela a Chryzantéma" << endl;
  }
};

struct GeneratorKvetin {
  Kvetina* operator()() {
    switch(rand() % 3) {
      default:
      case 0: return new Gladiola;
      case 1: return new Narciska;
      case 2: return new Chryzantema;
    }
  }
};

int main() {
  srand(time(0)); // inicializovat generátor náhodných čísel
  vector<Kvetina*> v(10);
  generate(v.begin(), v.end(), GeneratorKvetin());
  vector<Kvetina*>::iterator it;
  // Je to téměř, jako kdybych přidal virtuální funkci 
  // vytvářející textovou reprezentaci květiny.
  StringVal sval;
  for(it = v.begin(); it != v.end(); it++) {
    (*it)->prijmout(sval);
    cout << string(sval) << endl;
  }
  // Provést "Včelí" operace se všemi objekty:
  Vcela vcela;
  for(it = v.begin(); it != v.end(); it++)
    (*it)->prijmout(vcela);
  purge(v);
} ///:~
