#include "parser-utils.h"
#include <iostream>

const char kCellChar = 'c';
const char kPileChar = 'r';

/* GetLine()
 * Gets a string from the user.
 */
string GetLine()
{
	string result;
	getline(cin, result);
	return result;
}

/* PressEnterToContinue()
 * Waits for the user to press ENTER.
 */
void PressEnterToContinue()
{
	cout << "Press ENTER to continue..." << endl;
	GetLine();
}

/* Read an integer, prompting until the user enters valid data. */
int GetInteger()
{
	while(true)
	{
		stringstream converter;
		converter << GetLine(); // Read data and load into the stream.
		
		/* Try to read an int. */
		int result;
		converter >> result;
		
		/* If we read an int successfully, see if anything's left over. */
		if(!converter.fail())
		{
			/* Try to read a single char.  In class we used a string, but
			 * this approach works as well.
			 */
			char remaining;
			converter >> remaining;
			
			/* If the stream broke, we ran out of characters and are done. */
			if(converter.fail())
				return result;
			else
				cout << "Unexpected character: " << remaining << endl;
		}
		else
			cout << "Please enter an integer." << endl;
		
		cout << "Retry: ";
	}
}

/* Returns whether there is no more data in s.  The way this works is
 * similar to the way that GetInteger works... it tries to read a single
 * character from the stringstream and checks whether this puts the stream
 * into a fail state.  If so, there was no data and the stream is at
 * end-of-input.  Otherwise, there was data, and the stream was not at the
 * end of its input.
 */
bool IsEndOfInput(stringstream& s)
{
	char leftover;
	s >> leftover;
	return s.fail();
}

/* Parses a location out of a stringstream, returning whether the
 * operation succeeded.  Locations are represented as a character
 * followed by a single integer digit, such as c0 or r1.
 */
bool ParseLocation(stringstream& s, placeT& result)
{
	/* Read a token out of the stringstream. */
	string token;
	s >> token;

	/* If this broke the stream or the token isn't two characters
	 * long, we failed.
	 */
	if(s.fail() || token.size() != 2)
		return false;

	/* Based on the type of the character, return the upper bound for
	 * the value of the index.
	 */
	int maxIndex;
	switch(token[0])
	{
	case kCellChar:
		/* Cells range from 0 to kNumCells. */
		result.type = Cell;
		maxIndex = kNumCells;
		break;
	case kPileChar:
		/* Rows range from 0 to kNumPiles. */
		result.type = Pile;
		maxIndex = kNumPiles;
		break;
	default:
		/* Whoops!  No idea what this is.  Return false to signal an
		 * error.
		 */
		return false;
	}

	/* Get the index, which is the numeric value of the second character
	 * minus the zero character.
	 */
	result.index = token[1] - '0';

	/* This worked if the index is in bounds. */
	return result.index >= 0 && result.index < maxIndex;
}

/* ConvertToLowerCase works by iterating over the string and applying
 * the tolower function to each character.  See <cctype> for more
 * info.
 */
string ConvertToLowerCase(string input)
{
	for(int i = 0; i < input.size(); ++i)
		input[i] = tolower(input[i]);
	return input;
}
