#include<iostream>
#include<sstream>
#include<string>

using namespace std;

//Functions created
int inputNumber();
bool isValidNumber(string input);
void playerOneInput(int numbers[]);
bool getPlayerTwoGuess();
void startGame();
//Functions created end

int main(int argc, char** argv) {
	startGame(); //Begins the game
	return 0;
}

/*
 *	Function returns a number entered by the player
 */
int inputNumber() {
	stringstream stream; //Used to convert string to a number value
	string input = ""; //Stores the input within a string
	int number; //Stores the value that gets entered

	getline(cin, input); //Gets the input given by player
	stream.str(input);
	stream >> number;
	stream.clear();

	/*
	 *	Calls the boolean function to check if valid number
	 *	if it is true and the input is not empty
	*/
	if (!input.empty() && isValidNumber(input) == true) {
		return number; //It will return the number entered by user
	}

}


/*
 *	This boolean function will be used to return the guess that player two makes
 *	If they guess 'h', it will return true
 *	Else If they guess 'l', it will return false
 */
bool getPlayerTwoGuess() {
	bool guessedHigher; //Boolean variable used to return true or false
	bool validGuessInput = false; //Used in a while loop to repeat the input if user enters something other than H or L
	string guessInput; //Stores the answer player two inputs within string (Allows use of guessInput.empty() function to check if user did not enter anything)


	while (validGuessInput == false) { //While this is equal to false

		getline(cin, guessInput); //Gets the input given by player

		if (!guessInput.empty() && (guessInput == "h" || guessInput == "H")) { //If the input is not empty && guess equals to H 
			guessedHigher = true; //Assigns the guess as true
			return guessedHigher; //Returns true
			validGuessInput = true; //Assigns the input as true and breaks the loop
		}
		else if (!guessInput.empty() && (guessInput == "l" || guessInput == "L")) { //Else if the input is not empty && guess equals to L 
			guessedHigher = false; //Assigns the guess as false
			return guessedHigher; //Function Returns false
			validGuessInput = true; //Assigns the input as true and breaks the loop
		}
		else { //Else, if none of those conditions above meet, get the user to re-enter
			cout << "Error. Re-enter H or L: ";
		}
	}
}

/*
 * This function will handle the first players input
 * The numbers array will store the numbers that are input by the player
 * The player can only enter 7 numbers, so the for loop will go upto 6 and stop
 * as an arrays index starts at 0
 */
void playerOneInput(int numbers[]) {

	cout << "\nPlayer 1 - Please enter 7 values." << endl;

	for (int num = 0; num < 7; num++) { //Increments by 1 upto 6
		cout << "Enter number " << num + 1 << ": ";
		numbers[num] = inputNumber(); //Value of the index it is on will be assigned the number that is input

		if (numbers[num] >= 1 && numbers[num] <= 10) { //Checks If the number entered is within the range of 1 and 10
			continue; //If so, continues onto the next increment
		}
		else { //Else if not, the game restarts
			cout << "Error the number entered is not in the range of 1 to 10. Restarting." << endl;
			startGame();
			break;
		}

	}
}

/*
 *	Function which will start and handle the game
 */
void startGame() {
	int playerOneNumbers[7]; //Stores the values from the input of player one
	int playerTwoGuess = 0; //Will be used to get the guess player two is on (Starts at 0 for use of getting the values from the array player ones' numbers are stored)

	cout << "--- Higher or lower game ---" << endl;
	cout << "Player 1 will enter 7 values within the range of 1 to 10, and Player 2 has to \ntry guess whether the number displaying is higher or lower than the next." << endl;

	//Calls function to ask player one to enter values, values input will be stored in the playerOneNumbers array variable above
	playerOneInput(playerOneNumbers);


	//Player Two guessing will be handled below

	cout << "Player 2 - Try and guess if the next number will be higher or lower by typing H or L" << endl;
	cout << "The first number is: " << playerOneNumbers[0] << endl; //Displays the first value which is stored in index 0 of the array

	while (playerTwoGuess < 7) { //While they have guessed less than 7 times, this loop will continue playing

		if (playerTwoGuess == 6) { //Loop 6 determines that they won as they would have gotten through all guesses
			cout << "Congratulations, Player 2 has won!" << endl;
			exit(0); //Ends program
			break;
		}

		if (playerTwoGuess >= 1) {
			cout << "Correct. The next number is: " << playerOneNumbers[playerTwoGuess] << endl; //Displays the next value which is stored in index of which guess the player is on
		}

		cout << "Player 2 - Is the next number H or L? ";

		bool guessedHigher = getPlayerTwoGuess(); //boolean variable which calls a boolean function to store their answer

		//If the next Number is the same number of what it's displaying, and guessed higher or less than, continues
		if ((guessedHigher == true || guessedHigher == false) && playerOneNumbers[playerTwoGuess + 1] == playerOneNumbers[playerTwoGuess]) {
			playerTwoGuess++;
			continue;
		}

		//If the next number is greater than the next number and they guessed greater, continue
		if (guessedHigher == true && playerOneNumbers[playerTwoGuess + 1] > playerOneNumbers[playerTwoGuess]) {
			playerTwoGuess++;
			continue;
		}

		//If the next number is less than the next number and they guessed greater, breaks from the loop and ends program
		else if (guessedHigher == true && playerOneNumbers[playerTwoGuess + 1] < playerOneNumbers[playerTwoGuess]) {
			cout << "You have lost the game." << endl;
			exit(0);
			break;
		}

		//If they did not guess higher and the next number was less than the number displaying, continue
		if (guessedHigher == false && playerOneNumbers[playerTwoGuess + 1] < playerOneNumbers[playerTwoGuess]) {
			playerTwoGuess++; //Increments the guess player two is on
			continue; //continues onto next loop
		}

		//If they did not guess higher and the next number was greater than the one displaying, breaks from the loop and ends program
		else if (guessedHigher == false && playerOneNumbers[playerTwoGuess + 1] > playerOneNumbers[playerTwoGuess]) {
			cout << "You have lost the game." << endl;
			exit(0);
			break;
		}
	}
}

/*
 *	Boolean function that will return if the input given, is a number
 *	This function checks the ASCII codes of the characters stored in the string parameter
 *	ASCII Codes 48 to 57 = numbers from 0 to 9
 */
bool isValidNumber(string input) {
	int lengthOfInput = (int)input.length(); //Variable that is assigned the length of the input, casted with int to get the number

	int index; //Variable will be used in a loop to go through each index of the input

	int asciiCode; //Variable will store the ascii code of the characters 

	for (index = 0; index < lengthOfInput; index++) { //Loop to increment through each character of the input up to the length of it

		//asciiCode gets assigned the ascii value of the index it is on the input(the character), and does this by casting it with an int 
		asciiCode = (int)(input[index]);

		//If the ascii code is less than 48 or is greater than 57
		if (asciiCode < 48 || asciiCode > 57) { //That would mean it is not a number between 0 to 9. 
			return false; //returns false, not a valid number
		}
	}
	return true; //If it did not return false in the loop, the text is a valid number
}