#ifndef INC_MORESTRING
#define INC_MORESTRING

#include "moreString.h"
#include <cmath>

string ucase(string str)
{	// convert all characters to uppercase

	string result = "";
	for ( unsigned int i=0; i < str.length(); i++ )
	{
		result.append(1,toupper(str[i]));
	}
	return result;
}

string lcase(string str)
{	// convert all characters to lowercase

	string result = "";
	for ( unsigned int i=0; i < str.length(); i++ )
	{
		result.append(1,tolower(str[i]));
	}
	return result;
}

string ucfirst(string str)
{
	// converts all characters to lowercase except if it is the first of a word,
	// then convert to uppercase

	string result = "";
	bool inWord=false;
	char c, uc, lc;

	for ( unsigned int i=0; i < str.length(); i++ )
	{
		c=str[i];	uc=toupper(c);	lc=tolower(c);
		if ( lc >= 'a' && lc <='z' )
		{	
			if ( inWord ) 
			{   // already in a word
				result.append(1,lc);
			} else {
				// start of a new word
				inWord=true;
				result.append(1,uc);
			}
		} else {
			// no longer in a word
			if ( lc != '\'' ) inWord=false;
			result.append(1,c);
		}
	}

	return result;
}

string ltrim(string str)
{	// trim white space off the left
	if ( str.length() < 1 ) return str;

	unsigned int pos=0;
	while ( pos < str.length() && str[pos] <= 32 )
	{
		pos++;
	};

	return str.substr(pos,str.length()-pos);

}

string rtrim(string str)
{	// trim white space off the right
	if ( str.length() < 1 ) return str;

	unsigned int pos=str.length()-1;
	while ( pos >= 0 && str[pos] <= 32 )
	{
		pos--;
	};

	return str.substr(0,pos+1);
}

string trim(string str)
{	// trim white space from left & right
	return ltrim(rtrim(str));
}

string left(string str, int count)
{	// return only the [count] characters from the left
	return str.substr(0,count);
}

string right(string str, int count)
{	// return only the [count] characters from the right
	return str.substr(str.length()-count,count);
}

int strpos(string haystack, string needle, int start)
{
	// returns position of the start of 'needle' within 'haystack'
	// or -1 if it's not there.
	int result=-1;

	if ( needle.length() > haystack.length() )
	{	cout << "\nTrying to look for a haystack in a needle?! (needle cannot be larger than the haystack)\n";	
		exit (0);
	}

	// convert both to lcase, no case sensitivity
	haystack=lcase(haystack);
	needle=lcase(needle);

	// look for needle in haystack	
	unsigned int pos=start;
	unsigned int end=haystack.length()-needle.length();

	do
	{
		if ( haystack.substr(pos,needle.length()) == needle )
			result=pos;
		pos++;
	} while (pos <= end && result == -1);

	return result;
}

vector<string> split(string str, char delim)
{
	// returns a vector of strings out of the single string [str]
	// delimidated by [delim] (default ',')

	vector<string> elements;

	string currentElement;
	for ( unsigned int i=0; i < str.length(); i++ )
	{
		if ( str[i] != delim ) {
			currentElement.append(1,str[i]);
		}
		if ( str[i] == delim || i==str.length()-1 )
		{
			elements.push_back(currentElement);
			currentElement="";
		}
	}

	return elements;
}

int charCount(string str, string search)
{
	if ( str.length() < 1 ) { return 0; }

	// returns the number of occurances of string [search] in the string
	int count=0;
	int i=-1;

	while ( i < static_cast<int>(str.length()) )
	{
		i=strpos(str,search,i+1);
		if ( i >= 0 ) 
			count++;
		else
			break;
	};

	return count;
}
int charCount(string str, char search)
{	// wrapper function that allows you to use charCount with a 
	// char instead of string for search

	string strSearch;
	strSearch.append(1,search);
	return charCount(str,strSearch);
}

string titleize(string theTitle)
{
	// changes "the lord of the rings" to "Lord of the Rings, The"
	const int NUM_SMALLS=8;

	string smallword[NUM_SMALLS];
	smallword[0]="the";
	smallword[1]="for";
	smallword[2]="of";
	smallword[3]="in";
	smallword[4]="at";
	smallword[5]="it";
	smallword[6]="on";
	smallword[7]="a";

	vector<string> words=split(theTitle,' ');

	theTitle.clear();

	for ( unsigned int i=0; i < words.size(); i++ )
	{
		words[i]=lcase(words[i]);
		bool cap=true;
		for ( int j=0; j < NUM_SMALLS; j++ )
		{
			if ( smallword[j] == words[i] )
			{
				cap=false;
				break;
			}
		} // end for j
		if ( !( "the" == words[i] && 0 == i) )
		{
			if ( cap ) words[i]=ucfirst(words[i]);
			if ( theTitle.length() > 0 ) theTitle.append(" ");			
			theTitle.append(words[i]);
		}
		
	} // end for i

	if ( "the" == words[0] )
		theTitle.append(", The");

	return theTitle;
}

string displayTitle(string theTitle)
{
	// changes "Lord of the Rings, The" to "The Lord of the Rings"
	string result;
	if ( theTitle.length() > 5 )
	{
		string last5=right(theTitle,5);
		last5=lcase(last5);
		if ( ", the" == last5 )
		{
			// movie title ends in ", The", put it at the start instead
			result="The ";
			result.append(left(theTitle,theTitle.length()-5));
		} else {
			// movie title doesn't end with ", The"
			result=theTitle;
		}
	} else {
		// movie title isn't long enough to have ", The" at the end
		result=theTitle;
	}

	return result;
}

long long stringToLongLong(string num)
{
	// used for converting a timestamp in string format into a number

	long long ago = 0;
	double digit=0;
	int i=num.length()-1;

	for ( ; i >= 0; i-- )
	{
		ago+=(num[i]-48) * pow(10.0,digit);
		digit++;
	}
	return ago;
}

#endif