/*
 *  Hangman.cpp
 *  Hangman
 *
 *  Created by Jesper Fyhr Knudsen.
 *  Copyright 2010 Fyhr. All rights reserved.
 *
 */

#include <iostream>
#include <string>
#include <algorithm>
#include "stdlib.h"
#include "Hangman.h"

using namespace std;

Hangman::Hangman()
{
	Words[0] = "Hello World"; Words[1] = "Life sucks"; Words[2] = "Life is a bitch and then you die"; Words[3] = "Jesper F Knudsen"; Words[4] = "Spherical"; Words[5] = "Cider house rules"; Words[6] = "Left for Dead"; Words[7] = "Hangman is the best";
	AllowedLetters[0] = 'A'; AllowedLetters[1] = 'B'; AllowedLetters[2] = 'C'; AllowedLetters[3] = 'D'; AllowedLetters[4] = 'E'; AllowedLetters[5] = 'F'; AllowedLetters[6] = 'G'; AllowedLetters[7] = 'H'; AllowedLetters[8] = 'I'; AllowedLetters[9] = 'J'; AllowedLetters[10] = 'K'; AllowedLetters[11] = 'L'; AllowedLetters[12] = 'M'; AllowedLetters[13] = 'N'; AllowedLetters[14] = 'O'; AllowedLetters[15] = 'P'; AllowedLetters[16] = 'Q'; AllowedLetters[17] = 'R'; AllowedLetters[18] = 'S'; AllowedLetters[19] = 'T'; AllowedLetters[20] = 'U'; AllowedLetters[21] = 'V'; AllowedLetters[22] = 'W'; AllowedLetters[23] = 'X'; AllowedLetters[24] = 'Y'; AllowedLetters[25] = 'Z';
	WordsSize    = 8;
	GuessesLeft  = 6; // number of wrong guesses

	// Select random word
	string word = Words[ rand( ) % WordsSize ];
	transform( word.begin(), word.end(), word.begin(), ::toupper );
	
	// Obfuscate word, but retain whitespace
	string obfuscatedWord = ObfuscateWord( &word );
	
	while( RunGameLoop( &word ) )
	{
		
	}
}

bool Hangman::RunGameLoop( string* originalWord )
{
	string obfuscatedWord = ObfuscateWord( originalWord );
	string word           = *originalWord;
	
	system( "Clear" );
	
	// show current known word
	cout << "Current word: " << obfuscatedWord << endl;
	
	// Show number of guesses left
	cout << "You have " << GuessesLeft << (GuessesLeft == 1 ? " Guesses left" : " Guess left") << endl;
	
	// cin - user input
	string userInput;
	
	cout << "Either type in a letter or write Quit, to quit hangman" << endl;
	cin >> userInput;
	
	// makes the input uppercase to elliminate any case issues
	transform( userInput.begin(), userInput.end(), userInput.begin(), ::toupper );
	
	// if - validate user input
	if( !UserInputIsValid( &userInput ) )
		return RunGameLoop( &word );
	
	// if - handle userinput, either quit or continue with game logic
	// if - quit, return false
	if( "QUIT" == userInput )
		return false;
	
	// if - a letter add to quessed letters array
	if( !LetterHasBeenUsedBefore( &userInput ) )
	{		
		if( word.find( userInput[0] ) == -1 )
			GuessesLeft--;
		
		obfuscatedWord = ObfuscateWord( &word );
	}
		
	// if - known word is the same as the original word, game is won
	if( word == obfuscatedWord )
	{
		cout << "Congratulations you guessed the word" << endl;
		return false;
	}
	
	// if - all guesses are used game is lost
	if( GuessesLeft == 0 )
	{
		cout << "Game Over" << endl;
		return false;
	}
	
	return true;
}

string Hangman::ObfuscateWord( string* wordToObfuscate )
{
	string obfuscatedWord;
	string word = *wordToObfuscate;
	
	for( int i = 0; i < word.size(); i++ ) 
	{
		if( word[i] == ' ' )
			obfuscatedWord += " ";
		else
		{
			if( Guesses.find( word[i] ) != -1 )
				obfuscatedWord += word[i];
			else
				obfuscatedWord += "*";
		}
	}
	
	return obfuscatedWord;
}

bool Hangman::UserInputIsValid( string* userInput )
{
	string input = *userInput;
	
	// if it's the QUIT command return true
	if( input == "QUIT" )
		return true;
	
	// if it's not a single char return false
	if( input.size() != 1 )
		return false;
		
	// Check the allowed letters
	for( int i = 0; i < sizeof( AllowedLetters ); i++ )
	{
		if( AllowedLetters[i] == input[0] )
			return true;
	}
	
	return false;
}

bool Hangman::LetterHasBeenUsedBefore( string* userInput )
{
	if( Guesses.find( userInput[0] ) == -1 )
	{
		Guesses += userInput[0];
		return false;
	}
	
	return true;
}