/*
 *      decorator.cpp
 *      
 *      Copyright 2009 Heidenreich <mario86@mario86-laptop>
 *      
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */


#include <iostream>
#include <string>
using namespace std;

class Drink { //root interface
	private:
		float cost;
	public: 
		virtual void setCost(int c){cost=c;}
		virtual float getCost(){return cost;}
		virtual string getText(){return "a drink, hoOoray!";}
};

class Coffee: public Drink{ //implementation 1 of drink
	public:
		string getText(){return "coffee";}
		float getCost(){return 1.5f;}
};
class Espresso : public Drink{ //implementation 2 of drink
	public:
		string getText(){return "espresso";}
		float getCost(){return 2.0f;}
};

class DrinkDecorator : public Drink{ //root decorator class 
	protected:
		Drink *drink;
	public:
		DrinkDecorator(Drink *drinkToDecorate):drink(drinkToDecorate){}
		float getCost(){return drink->getCost();}
		string getText(){return drink->getText();}
};

class MilkDecorator :public DrinkDecorator{ //decorator implementation 1
	public:
		MilkDecorator(Drink *drink):DrinkDecorator(drink){}
		string getText();
		float getCost();
};
class SugarDecorator :public DrinkDecorator{ //decorator implementation 2
	public:
		SugarDecorator(Drink *drink):DrinkDecorator(drink){}
		string getText();
		float getCost();
};

string MilkDecorator::getText(){
	return drink->getText()+" with milk"; //decorate the getText() operation
	
}
float MilkDecorator::getCost(){
	return drink->getCost()+1.0f; //call function of drink and add a price (postprocessing) 
}

string SugarDecorator::getText(){
	return "putting sugar in your "+drink->getText(); //kind of preprocessing
	
}
float SugarDecorator::getCost(){
	return drink->getCost()+0.5f;
}

int main(int argc, char** argv)
{
	Coffee *myCoffee = new Coffee(); //create coffee
	Drink *myDrink = new SugarDecorator(new MilkDecorator(myCoffee)); //decorate it
	
	cout << myDrink->getText() << endl;
	cout << "this makes " << myDrink->getCost()<<"€"; //do something with the decorated object
	return 0;
}
