#include <iostream>
#include <vector>
#include <sstream>
#include <string>

using namespace std;


class P {
private:
	string name;

public:
	P(string n) : name(n) {}

	virtual string toString() const {
		return "P_" + name + "\n";
	}

	virtual P * anpassen(int anzahl) {
		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;
	unsigned int anzahl_;


public:
	Bauteile(string n, int anzahl=1) : name(n), anzahl_(anzahl) {
	}

	void add(const P & p, int amount) {
		I i(p, amount);
		teile.push_back(i);
	}

	void setAnzahl(int n) {
		anzahl_ = n;
	}

	string toString() const {
		string s;
		s += to_string( anzahl_)  + "\n";
		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 anzahl) {
		bauteile.add(p, anzahl);
		anpassen(anzahl);
	}

	Moebel * anpassen(int anzahl) {
		// cout << "Moebel_adapt" << endl;
		this->bauteile.setAnzahl(anzahl);
		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;

}
