
//		First of many projects.  	
//					   		
// 		A simple application intended to be used as a personal dictionary. 
// 		Works using maps, and simple text files. Maps are modified first 
//		and then the changes are written onto the file.                       
//		
//		Started work on :- 28th September, 2011          
//		Finished on     :- 30th September, 2011	       
//
// 		Usage:- Personally this application should be quite useful since
//		I am looking to improve my vocabulary and I will use this to 
//		store the words that I have learnt.                  
// 		
//      This application can also be modified to be used as a config.
//      file editor   
//


#include <iostream>														
#include <fstream>
#include <map>
#include <vector>
#include <string>
#include <utility>
#include <algorithm>
#include <iterator>
#include <limits>

using std::cout;
using std::cin;
using std::map;
using std::vector;
using std::string;
using std::ofstream;
using std::ifstream;
using std::cerr;
using std::endl;
using std::pair;
using std::fstream;

class FileIO{
	public:
	
																				
		void writeToMap();												
		void writeToFile();												  
		void readFile();															
		void printMap();												
		void appMenu();													
		void searchFile();												
		void deleteFromMap();											
		static void initFile(string&);									

		
	private:
		pair<string,string> splitString(const string&,char);	       	
		static map<string,string> file;
		static string nameOfTheFile;
		string name;
		string value;
		
		
};
map<string,string> FileIO::file;
string FileIO::nameOfTheFile;


// Initializes static variable nameOfTheFile to the name of file being processed
// name: initFile
// @param: name of the file being currently processed.
// @return: none

void FileIO::initFile(string& filename)
{
	FileIO::nameOfTheFile=filename;
	
}


// Displays the menu from where various functions can be carried out
// name: appMenu
// @param: none
// @return: none

void FileIO::appMenu()
{
	char choice;
	FileIO object;
	bool flag = true;
	while(flag)
	{
		
		cout<<endl;
		cout<<"Your wish is my command:"<<endl<<endl;
		cout<<"1. View Current File:"<<endl;
		cout<<"2. Write To Current File:"<<endl;
		cout<<"3. Search Current File:"<<endl;
		cout<<"4. Delete Entry from File:"<<endl;
		cout<<"5. Exit."<<endl;
		cin>>choice;
		switch(choice)
		{
			case '1':
				printMap();
				continue;
			case '2':
				writeToMap();
				continue;
			case '3':
				searchFile();
				continue;
			case '4':
				deleteFromMap();
				continue;
			case '5':
				writeToFile();
				flag=false;
				break;
			default:
				cout<<"Invalid Input Detected. Please try again, your Majesty."<<endl;
				continue;
		}
	}
}

// Reads the contents of the file into the map.
// name: readFile()
// @param: none
// @return: none

void FileIO::readFile()
{
		
	ifstream ifile(FileIO::nameOfTheFile.c_str());	string line="o";
	pair<string,string> split;
	map<string,string>::iterator iter=file.begin();
	while(getline(ifile,line))
	{
		split= splitString(line,':');
		file.insert(split);
	}

}

// Carries out changes to the map.
// name: writeToMap()
// @param: none
// @return: none

void FileIO::writeToMap()
{
	cin.ignore();
	char ans;
	do{
		cout<<"Enter the name of the entry; ";
		getline(cin,name);
		
		cout<<"Enter the value for the name; ";
		getline(cin,value);
	
		if(!file.insert(make_pair(name,value)).second)
		{
			cout<<"Error! Entry already present in file. Please try again, sire."<<endl;
			continue;
		}
		cout<<"The entry has been added, your majesty."<<endl;
		cout<<"Would thy majesty like to add another entry? (Y/N) ";
		cin>>ans;
		cin.ignore();
		cout<<endl;
	}while(ans=='y'||ans=='Y');
}

// Writes the contents in the map to the file being processed
// name: writeToFile()
// @param: none
// @return: none


void FileIO::writeToFile()
{
	ofstream ofile(FileIO::nameOfTheFile.c_str());
	for(map<string,string>::iterator iter=file.begin();iter!=file.end();++iter)
	{
		ofile<<iter->first<<":"<<iter->second<<endl;
	}
	ofile.close();
}

// Splits a string on ":". Used by the readFile() to read the file into map.
// name: splitString
// @param: string to be split, and character at which to split the string
// @return: pair containing the two strings obtained by splitting


pair<string,string> FileIO::splitString(const string& input, char ch)
{
	string::const_iterator symbol=find(input.begin(),input.end(),ch);
	name=string(input.begin(),symbol);
	
	string::const_reverse_iterator rsymbol=find(input.rbegin(),input.rend(),ch);
	value=string(rsymbol.base(),input.end());
	
	return make_pair(name,value);
}

// Prints the map to the console.
// name: printMap()
// @param: none
// @return: none


void FileIO::printMap()
{
	map<string,string>::iterator iter=file.begin();
	while(iter!=file.end())
	{
		cout<<iter->first<<" : "<<iter->second<<endl;
		++iter;
	}
	cout<<"Press ENTER to continue ...";
	cin.get();
	cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
}

// Checks whether the file specified by the filename exists.
// name: fileExists
// @param: File name entered by the user.
// @return: bool value indicating whether file could be opened or not.


bool fileExists(string& file)
{
	bool b=false;
	ifstream check(file.c_str());
	if(check)
		b=true;
	check.close();
	return b;
}

// Used to search the contents of the map.
// name: searchFile()
// @param: none
// @return: none


void FileIO::searchFile()
{
	cin.ignore();
	char ans='y',ans1;
	do{
		
		string search;
		cout<<"Enter the NAME of the entry to be searched OR exit/quit to go back to the Menu:";
		getline(cin,search);
		if(search=="quit" || search=="exit")
			appMenu();
		map<string,string>::iterator iter=file.find(search);
	
		if(iter==FileIO::file.end())
		{
			cout<<"The entry does not exist in the file."<<endl;
			cout<<"Would you like to add the entry?(Y/N)"<<endl;
			cin>>ans1;
			cin.ignore();
			if(ans1=='y'|| ans1=='Y')
				writeToMap();
			continue;
		}
		cout<<iter->first<<":"<<iter->second<<endl;
		cout<<"Would you like to do another search?(Y/N)";
		cin>>ans;
		cin.ignore();
	}while(ans=='y'||ans=='Y');
}

// Delete an entry from the map.
// name: deleteFromMap()
// @param: none
// @return: none


void FileIO::deleteFromMap()
{
	cin.ignore();
	string del;
	char ans;
	do{
	cout<<"Please enter the name of the entry you wish to delete: ";
	getline(cin,del);
	if(file.erase(del))
		cout<<"Word Removed."<<endl;
	else
		cout<<"Word "<<del<<" not found."<<endl;
	cout<<"Delete another word?(Y/N)";
	cin>>ans;
	cin.ignore();
	}while(ans=='y'||ans=='Y');
}
int main()
{
	string filename;
	bool quit=true;
	FileIO obj;
	do{
		
		cout<<"Enter the path to the file OR type exit or quit to exit the application: ";
		cin>>filename;
		if(filename=="quit"||filename=="exit")
			break;
		char ans;
		if(!fileExists(filename))
		{
			cout<<"File does not exist..."<<endl;
			cout<<"Do you want to create the file?(Y/N)";
			cin>>ans;
			if((ans=='y')||(ans=='Y'))
			{
			ofstream createfile(filename.c_str());
			obj.initFile(filename);
			obj.readFile();
			obj.appMenu();
			continue;
			}
			else
				continue;
			
		
		}
		obj.initFile(filename);
		obj.readFile();
		obj.appMenu();
	}while(quit);

	
	return 0;
}

