#include <iostream>
#include <vector>

using namespace std;


class P {
  private:
    string name;
    
  public:
    P(string n) : name(n) {}
    
    virtual string toString() const {
		return "P_" + name +"\n" ;
	}
	
	virtual P * adapter(double nbFois) {
		return this;
	}
	
};



class I {
  public:
    I(const P & p_, int a) : p(p_), amount(a) {
	}
	
	string desc() const {
	   string s;
	   s += " " + to_string(amount) + " * ";
	   s += " I_";
	   // call P::toString or Moebel::toString() ?
	   s += p.toString();
	   
	   return s;
	}
  
  private:
    const P & p;  
    int amount;
  
};


class Bauteile {
	
	private:
	  vector<I> teile;
	  string name;
	  
	public:
	   Bauteile(string n) : name(n) {
	   }
	   
	   void add(const P & p, int amount) {
		   I i(p, amount);
		   teile.push_back(i);
	   }
	   
	   string toString() const {
		   string s;
		   for (auto i : teile) {
			   s += "  ";
			   s += i.desc() + "\n";
		   }
		   return s;
	   }
	   

};


class Moebel : public P {
	
	private:
	  Bauteile bauteile;
	
	
	public:
	
	Moebel(string n) : P(n), bauteile(n) {
	}
	
	string toString() const {
		string s;
		s += "Moebel ";
		s += P::toString();
		s += bauteile.toString();
		
		return s;
	}
	
	void addToBauteile(const P & p, int amount) {
		bauteile.add(p, amount);
	}

	Moebel * adapter(double nbFois) {
		cout << "Moebel_adapt" << endl;
		return this;
	}
	

};

int main() {

  // Bauteile
  P p1("schrauben");
  P p2("brett");
  
  Moebel regal("Regal");
  regal.addToBauteile(p1, 1);
  regal.addToBauteile(p2, 4);
  
  cout << regal.toString() << endl;
  
  P p3("holztuer");
  Moebel grosses_regal("Grosses_regal");
  grosses_regal.addToBauteile(p3, 2);
  grosses_regal.addToBauteile(regal, 2);
  
  cout << grosses_regal.toString() << endl;
  

  return 0;
  
}
