//File Recipe.h - contains Recipe class
//Code has been adapted from previous Java assignment

//Make sure the file hasn't been included already
#ifndef _recipe_h
#define _recipe_h

#include "StringFunctions.h"
#include <string>

//Definition of Recipe class
class Recipe{
public:
	//Constructors
	Recipe()
		: name("None"), rating("None"), contributor("None"), spices("None"), source("None"), category("None"),
		ingredients("None"), directions("None"){
			initTags();
	}
	Recipe(string aName, string aRating, string aContributor, string someSpices, string aSource, string aCategory,
		string aDescription, string someIngredients, string someDirections)
		: name(aName), rating(aRating), contributor(aContributor), spices(someSpices), source(aSource), category(aCategory),
		ingredients(someIngredients), directions(someDirections){
			initTags();
	}
	Recipe(const Recipe& aRecipe)
		: name(aRecipe.name), rating(aRecipe.rating), contributor(aRecipe.contributor), spices(aRecipe.spices), source(aRecipe.source),
		category(aRecipe.category), ingredients(aRecipe.ingredients), directions(aRecipe.directions){
			initTags();
	}

	//Initializer method for tags
	void initTags(){
		startTag = "<recipe>";  
		endTag = "</recipe>";
		recipeNameStartTag = "<recipe name>";
		recipeNameEndTag = "</recipe name>"; 
		ratingStartTag = "<rating>"; 
		ratingEndTag = "</rating>";
		contributorStartTag = "<contributor>";  
		contributorEndTag = "</contributor>";
		sourceStartTag = "<source>";  
		sourceEndTag = "</source>";
		categoryStartTag = "<category>";  
		categoryEndTag = "</category>";
		descriptionStartTag = "<description>";  
		descriptionEndTag = "</description>";
		spicesStartTag = "<spices>";
		spicesEndTag = "</spices>";
		ingredientsStartTag = "<ingredients>";  
		ingredientsEndTag = "</ingredients>";
		directionsStartTag = "<directions>";  
		directionsEndTag = "</directions>";
	}

	//Get methods
	string getStartTag(){return startTag;}			//Returns the start tag
	string getEndTag(){return endTag;}				//Returns the end tag
	string getRating(){return Trim(rating);}		//Returns the rating
	string getName(){return Trim(name);}			//Returns the name
	string getNumber(){return Trim(contributor);}	//Returns the contributor's student number
	string getSpice(){return Trim(spices);}			//Returns the spices
	
	//Print method
	void printOn(ostream & out) {
		countLinesDisplayed = 0;
		
		out << "==============================================================";
		out << "\nNAME: \n";
		displaySection(out, Trim(name));
		out << "\nRATING: \n";
		displaySection(out, Trim(rating));
		out << "\nCONTRIBUTOR: \n";
		displaySection(out, Trim(contributor));
		out << "\nSPICES: \n";
		displaySection(out, Trim(spices));
		out << "\nSOURCE: \n";
		displaySection(out, Trim(source));
		out << "\nCATEGORY: \n";
		displaySection(out, Trim(category));
		out << "\nDESCRIPTION: \n";
		displaySection(out, Trim(description));
		out << "\nINGREDIENTS: \n";
		displaySection(out, Trim(ingredients));
		out << "\nDIRECTIONS: \n";
		displaySection(out, Trim(directions));
	}

	//XML methods
	void printXMLOn(string initialIndent, ostream & out) {
		string indent = initialIndent;
		string tab = "\t";
		
		//Print the start tag, <recipe>
		out << indent << startTag;
		//Increase the indent, to follow proper XML format
		indent = indent + tab;
		
		//Print out each field with its tags
		out << indent << recipeNameStartTag << indent << Trim(name) << indent << recipeNameEndTag;
		out << indent << ratingStartTag << indent << Trim(rating) << indent << ratingEndTag;
		out << indent << contributorStartTag << indent << Trim(contributor) << indent << contributorEndTag;
		out << indent << spicesStartTag << indent << Trim(spices) << indent << spicesEndTag;
		out << indent << sourceStartTag << indent << Trim(source) << indent << sourceEndTag;
		out << indent << categoryStartTag << indent << Trim(category) << indent << categoryEndTag;
		out << indent << descriptionStartTag << indent << Trim(description) << indent << descriptionEndTag;
		out << indent << ingredientsStartTag << indent << Trim(ingredients) << indent << ingredientsEndTag;
		out << indent << directionsStartTag << indent << Trim(directions) << indent << directionsEndTag;
		
		//Decrease the indent, to be in line with the start tag
		indent = initialIndent;
		//Print the end tag, </recipe>
		out << indent << endTag;
	}
	void setXMLField(string xmlField, string text) {
		//Trim the field
		string input = Trim(xmlField);
		//If the field starts with a certain XML tag, put the text into its proper variable
		if(StartsWith(input, recipeNameStartTag) == true)
			name = text;
		if(StartsWith(input, ratingStartTag) == true)
			rating = text;
		if(StartsWith(input, contributorStartTag) == true)
			contributor = text;
		if(StartsWith(input, spicesStartTag) == true)
			spices = text;
		if(StartsWith(input, sourceStartTag) == true)
			source = text;
		if(StartsWith(input, categoryStartTag) == true)
			category = text;
		if(StartsWith(input, descriptionStartTag) == true)
			description = text;
		if(StartsWith(input, ingredientsStartTag) == true)
			ingredients = text;
		if(StartsWith(input, directionsStartTag) == true)
			directions = text;
	}
	bool isXMLStartTag(string aTagString){
		string input = aTagString;
		//If the input is the same as a given tag, return true
		if(input.compare(startTag) == 0)
			return true;      
		if(input.compare(recipeNameStartTag) == 0)
			return true;
		if(input.compare(ratingStartTag) == 0)
			return true;
		if(input.compare(contributorStartTag) == 0)
			return true;
		if(input.compare(spicesStartTag) == 0)
			return true;
		if(input.compare(sourceStartTag) == 0)
			return true;
		if(input.compare(categoryStartTag) == 0)
			return true;
		if(input.compare(descriptionStartTag) == 0)
			return true;
		if(input.compare(ingredientsStartTag) == 0)
			return true;
		if(input.compare(directionsStartTag) == 0)
			return true;
		//If the text doesn't match any of the above tage, return false
		return false;
	}
	bool isXMLEndTag(string aTagString){
		string input = aTagString;
		//If the input is the same as a given tag, return true
		if(input.compare(endTag) == 0)
			return true;      
		if(input.compare(recipeNameEndTag) == 0)
			return true;
		if(input.compare(ratingEndTag) == 0)
			return true;
		if(input.compare(contributorEndTag) == 0)
			return true;
		if(input.compare(spicesEndTag) == 0)
			return true;
		if(input.compare(sourceEndTag) == 0)
			return true;
		if(input.compare(categoryEndTag) == 0)
			return true;
		if(input.compare(descriptionEndTag) == 0)
			return true;
		if(input.compare(ingredientsEndTag) == 0)
			return true;
		if(input.compare(directionsEndTag) == 0)
			return true;
		//If the text doesn't match any of the above tage, return false
		return false;
	}
	bool isXMLTag(string aTagString){
		return (isXMLStartTag(aTagString) || isXMLEndTag(aTagString));
	}

	//Destructor
	~Recipe(){
		//No memory allocated in class
	}

private:
	//The tags
	string startTag;  
	string endTag;
	string recipeNameStartTag;
	string recipeNameEndTag; 
	string ratingStartTag; 
	string ratingEndTag;
	string contributorStartTag;  
	string contributorEndTag;
	string sourceStartTag;  
	string sourceEndTag ;
	string categoryStartTag;  
	string categoryEndTag;
	string descriptionStartTag;  
	string descriptionEndTag;
	string spicesStartTag;
	string spicesEndTag;
	string ingredientsStartTag;  
	string ingredientsEndTag;
	string directionsStartTag;  
	string directionsEndTag;

	//The fields
	string name;
	string rating;		//Bland, Mild, Medium, Hot, Fierce 
	string contributor;
	string spices;
	string source;
	string category;
	string description;
	string ingredients;
	string directions;

	int countLinesDisplayed;	//Used in the printOn and displaySection methods
	
	//Displays the given text, prompting the user for more after a certain number of lines
	void displaySection(ostream & ostr, string sectionName){
		const int LINES = 20;		//Used to determine how many lines should be displayed before user is prompted for more
		//Convert string sectionName to char *
		//char * pch;
		char *token, *next_token;
		char delims[] = "\n";

		char * str;
		str = new char[sectionName.size()+1];
		strcpy_s(str, strlen(str), sectionName.c_str());
		
		//Check how many lines have been displayed already
		countLinesDisplayed+=3;		//For the title of the section
		if(countLinesDisplayed>LINES){
			ostr << "\nPress enter for more...";
    		while(getchar()!='\n');
    		countLinesDisplayed = countLinesDisplayed % (LINES + 1);
		}
		//Parse the text into individual lines
		token = strtok_s(str, delims, &next_token);
		//Get next line, display it, then check how many lines have been displayed so far
		while (token != NULL)
		{
			ostr << *token << "\n";
			countLinesDisplayed++;
			if(countLinesDisplayed>LINES){
				ostr << "\nPress enter for more...";
    			while(getchar()!='\n');
    			countLinesDisplayed = countLinesDisplayed % (LINES + 1);
			}
			token = strtok_s( NULL, delims, &next_token);		//Get next line
		}
	}
};

//Overloaded insertion operator for the Recipe class
ostream & operator<<(ostream & ostr, Recipe & r) {
     r.printOn(ostr);
     return ostr;
}
#endif
//End of Recipe.h