//: C10:Kolo.h
// 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.
// Definuje třídy pro sestavení kola.
// Ukazuje návrhový vzor Stavitel.
#ifndef BICYCLE_H
#define BICYCLE_H
#include <iostream>
#include <string>
#include <vector>
#include <cstddef>
#include "../purge.h"
using std::size_t;

class CastKola {
public:
  enum KCast { RAM, KOLO, SEDLO, PREHAZOVACKA,
    RIDITKA, ROZETA, BRASNA, TLUMIC, NCASTI };
private:
  KCast id;
  static std::string nazvy[NCASTI];
public:
  CastKola(KCast kc) { id = kc; }
  friend std::ostream&
  operator<<(std::ostream& os, const CastKola& kc) {
    return os << kc.nazvy[kc.id];
  }
};

class Kolo {
  std::vector<CastKola*> casti;
public:
  ~Kolo() { purge(casti); }
  void pridatCast(CastKola* kc) { casti.push_back(kc); }
  friend std::ostream&
  operator<<(std::ostream& os, const Kolo& b) {
    os << "{ ";
    for(size_t i = 0; i < b.casti.size(); ++i)
      os << *b.casti[i] << ' ';
    return os << '}';
  }
};

class StavitelKola {
protected:
  Kolo* produkt;
public:
  StavitelKola() { produkt = 0; }
  void vytvoritProdukt() { produkt = new Kolo; }
  virtual void sestavitRam() = 0;
  virtual void sestavitKolo() = 0;
  virtual void sestavitSedlo() = 0;
  virtual void sestavitPrehazovacku() = 0;
  virtual void sestavitRiditka() = 0;
  virtual void sestavitRozetu() = 0;
  virtual void sestavitBrasnu() = 0;
  virtual void sestavitTlumic() = 0;
  virtual std::string getNazevKola() const = 0;
  Kolo* getProdukt() {
    Kolo* temp = produkt;
    produkt = 0;  // opustit produkt
    return temp;
  }
};

class StavitelHorskehoKola : public StavitelKola {
public:
  void sestavitRam();
  void sestavitKolo();
  void sestavitSedlo();
  void sestavitPrehazovacku();
  void sestavitRiditka();
  void sestavitRozetu();
  void sestavitBrasnu();
  void sestavitTlumic();
  std::string getNazevKola() const { return "HorskeKolo";}
};

class StavitelCestovnihoKola : public StavitelKola {
public:
  void sestavitRam();
  void sestavitKolo();
  void sestavitSedlo();
  void sestavitPrehazovacku();
  void sestavitRiditka();
  void sestavitRozetu();
  void sestavitBrasnu();
  void sestavitTlumic();
  std::string getNazevKola() const { return "CestovniKolo"; }
};

class StavitelZavodnihoKola : public StavitelKola {
public:
  void sestavitRam();
  void sestavitKolo();
  void sestavitSedlo();
  void sestavitPrehazovacku();
  void sestavitRiditka();
  void sestavitRozetu();
  void sestavitBrasnu();
  void sestavitTlumic();
  std::string getNazevKola() const { return "ZavodniKolo"; }
};

class MechanikKola {
  StavitelKola* stavitel;
public:
  MechanikKola() { stavitel = 0; }
  void nastavitStavitele(StavitelKola* b) { stavitel = b; }
  void sestavit();
};
#endif // BICYCLE_H ///:~
