#include "slots.h"
#include <iostream>
#include <string>
#include <cmath>
#include <sstream> //  Needed For Integer To String Conversion
#include <ctime>
#include <cstdlib>

using namespace std;

// Function Prototypes
void QStringToString(QString original, string &final);
int StringToInteger(string original);
int charToInt(char character);
string integerToString(int value);


Slots::Slots(QWidget *parent)
    : QWidget(parent)
{
	ui.setupUi(this);
	
	// Connect Signals and Slots
	connect(ui.exitButton, SIGNAL(clicked()), this, SLOT(close()));
	connect(ui.pullButton, SIGNAL(clicked()), this, SLOT(pullLever()));
	
	// Load Player Information
	playerStats.totalMoney = 100000;
	playerStats.totalLosses = 0;
	playerStats.totalWins = 0;
	playerStats.progressiveValue = 0;
	
	// Set Randomizer
	srand((unsigned)time(0));
	
	// Update User Interface
	changeAllLCDNumberColors();
	ui.headerLabel->setText("<h1>Welcome to Slots!</h1>");
	
	
	ui.slotFrame->setLineWidth(10);
	ui.slotFrame->setVisible(true);
	string temp = "Total Money: " + integerToString(playerStats.totalMoney); 
	ui.moneyLabel->setText(temp.c_str());
	ui.betLineEdit->setText("10");
	ui.playsLineEdit->setText("1");
	// Change LCD Number Digits
	ui.lcdNumber1->setNumDigits(1);
	ui.lcdNumber2->setNumDigits(1);
	ui.lcdNumber3->setNumDigits(1);
	ui.lcdNumber4->setNumDigits(1);
	ui.lcdNumber5->setNumDigits(1);
	ui.lcdNumber6->setNumDigits(1);
	ui.lcdNumber7->setNumDigits(1);
	ui.lcdNumber8->setNumDigits(1);
	ui.lcdNumber9->setNumDigits(1);
	
	
	
}

Slots::~Slots()
{

}

void Slots::pullLever() {
	ui.pullButton->setEnabled(false);
	ui.messageLabel->setText("");
	changeAllLCDNumberColors();
	// Check Number Of Plays
	if (checkNumPlays() == false) {
		ui.pullButton->setEnabled(true);
		return;
	}
	// Check Bet
	if (checkBet() == false) {
		ui.pullButton->setEnabled(true);
		return;	
	}
	
	string plays;
	QStringToString(ui.playsLineEdit->text(), plays);
	for (int counter = 0; counter < StringToInteger(plays); counter++)  {
		changeAllLCDNumberColors();
		// Get Random Numbers For This Pull
		generateNumbers();
		// Update The LCD Digits For This Pull
		updateLCDNumbers();
		// Check To See If Player Won
		checkWin();
		QApplication::processEvents();
	}
	
	ui.pullButton->setEnabled(true);
}

bool Slots::checkWin() {
	bool winner = false;
	bool progressiveWinner = false;
	int mulitplier = 1;
	string temp;
	string bet;
	QStringToString(ui.betLineEdit->text(), bet);
	// Check To See If The Top Line Is A Winner
	if (digits[0] == digits[1] && digits[0] == digits[2]) {
		mulitplier *= 5;
		temp = "<h2><font color=green>Congratulations! You Win ";
		temp += integerToString(StringToInteger(bet) * mulitplier);
		temp += " Dollars!</font></h2>";
		ui.messageLabel->setText(temp.c_str());
		changeLCDNumberToWinColor(1);
		changeLCDNumberToWinColor(2);
		changeLCDNumberToWinColor(3);
		winner = true;
	}
	
	// Check To See If The Middle Line Is A Winner
	if (digits[3] == digits[4] && digits[3] == digits[5]) {
		mulitplier *= 10;
		temp = "<h2><font color=green>Congratulations! You Win ";
		temp += integerToString(StringToInteger(bet) * mulitplier);
		temp += " Dollars!</font></h2>";
		ui.messageLabel->setText(temp.c_str());
		changeLCDNumberToWinColor(4);
		changeLCDNumberToWinColor(5);
		changeLCDNumberToWinColor(6);
		winner = true;
	}
	
	// Check To See If The Bottom Line Is A Winner
	if (digits[6] == digits[7] && digits[6] == digits[8]) {
		mulitplier *= 5;
		temp = "<h2><font color=green>Congratulations! You Win ";
		temp += integerToString(StringToInteger(bet) * mulitplier);
		temp += " Dollars!</font></h2>";
		ui.messageLabel->setText(temp.c_str());
		changeLCDNumberToWinColor(7);
		changeLCDNumberToWinColor(8);
		changeLCDNumberToWinColor(9);
		winner = true;
	}
	
	// Check To See If The First Vertical Is A Winner
	if (digits[0] == digits[3] && digits[0] == digits[6]) {
		mulitplier *= 3;
		temp = "<h2><font color=green>Congratulations! You Win ";
		temp += integerToString(StringToInteger(bet) * mulitplier);
		temp += " Dollars!</font></h2>";
		ui.messageLabel->setText(temp.c_str());
		changeLCDNumberToWinColor(1);
		changeLCDNumberToWinColor(4);
		changeLCDNumberToWinColor(7);
		winner = true;
	}
	
	// Check To See If The Second Vertical Is A Winner
	if (digits[1] == digits[4] && digits[1] == digits[7]) {
		mulitplier *= 3;
		temp = "<h2><font color=green>Congratulations! You Win ";
		temp += integerToString(StringToInteger(bet) * mulitplier);
		temp += " Dollars!</font></h2>";
		ui.messageLabel->setText(temp.c_str());
		changeLCDNumberToWinColor(2);
		changeLCDNumberToWinColor(5);
		changeLCDNumberToWinColor(8);
		winner = true;
	}
	
	// Check To See If The Third Vertical Is A Winner
	if (digits[2] == digits[5] && digits[2] == digits[8]) {
		mulitplier *= 3;
		temp = "<h2><font color=green>Congratulations! You Win ";
		temp += integerToString(StringToInteger(bet) * mulitplier);
		temp += " Dollars!</font></h2>";
		ui.messageLabel->setText(temp.c_str());
		changeLCDNumberToWinColor(3);
		changeLCDNumberToWinColor(6);
		changeLCDNumberToWinColor(9);
		winner = true;
	}
	
	// Check To See If The Progessive Is A Winner
	if (digits[0] == digits[2] && digits[6] == digits[8] && digits[4] == digits[8] && digits[0] == digits[4]) {
		progressiveWinner = true;
		temp = "<h2><font color=green>Progressive Winner! You Win ";
		temp += integerToString(playerStats.progressiveValue);
		temp += " Dollars!</font></h2>";
		ui.messageLabel->setText(temp.c_str());
		changeLCDNumberToWinColor(0);
		changeLCDNumberToWinColor(2);
		changeLCDNumberToWinColor(4);
		changeLCDNumberToWinColor(6);
		changeLCDNumberToWinColor(8);
		
	}
	
	if (winner == false) {
		temp = "<h2>Sorry, You Have Lost ";
		temp += bet;
		temp += " Dollars.</h2>";
		ui.messageLabel->setText(temp.c_str());
		playerStats.totalLosses++;
		playerStats.progressiveValue += StringToInteger(bet) / 2;
		playerStats.totalMoney -= StringToInteger(bet);
		temp = "Total Losses: " + integerToString(playerStats.totalLosses);
		ui.numberLossesLabel->setText(temp.c_str());
		temp = "Progessive Ammount: " + integerToString(playerStats.progressiveValue);
		ui.progressiveLabel->setText(temp.c_str());
		temp = "Money: " + integerToString(playerStats.totalMoney);
		ui.moneyLabel->setText(temp.c_str());
		return false;
	} else if (progressiveWinner == true) {
		playerStats.totalWins++;
		playerStats.totalMoney += playerStats.progressiveValue;
		playerStats.progressiveValue = 0;
		temp = "Total Wins: " + integerToString(playerStats.totalWins);
		ui.numberWinsLabel->setText(temp.c_str());
		temp = "Money: " + integerToString(playerStats.totalMoney);
		ui.moneyLabel->setText(temp.c_str());
		temp = "Progessive Ammount: " + integerToString(playerStats.progressiveValue);
		ui.progressiveLabel->setText(temp.c_str());
		return true;
		
	} else {
		playerStats.totalWins++;
		playerStats.totalMoney += StringToInteger(bet);
		temp = "Total Wins: " + integerToString(playerStats.totalWins);
		ui.numberWinsLabel->setText(temp.c_str());
		temp = "Money: " + integerToString(playerStats.totalMoney);
		ui.moneyLabel->setText(temp.c_str());
		return true;
	}

}

void Slots::generateNumbers() {
	// Generates The Digits
	for (int counter = 0; counter < 9; counter++) {
		digits[counter] = (rand()%10) + 0;
	}
	
	// Increase odds of winning
	if (rand()%7 + 0 == 3) {
		digits[4] = digits[3];
		digits[5] = digits[3];
	}
	
	// Progressive Slot Winner
	if (rand()%100 + 0 == 57) {
		digits[0] = digits[2];
		digits[6] = digits[2];
		digits[8] = digits[2];
		digits[4] = digits[2];
	}
}

void Slots::updateLCDNumbers() {
	ui.lcdNumber1->display(digits[0]);
	ui.lcdNumber2->display(digits[1]);
	ui.lcdNumber3->display(digits[2]);
	ui.lcdNumber4->display(digits[3]);
	ui.lcdNumber5->display(digits[4]);
	ui.lcdNumber6->display(digits[5]);
	ui.lcdNumber7->display(digits[6]);
	ui.lcdNumber8->display(digits[7]);
	ui.lcdNumber9->display(digits[8]);
	
}

bool Slots::checkBet() {
	string bet;
	QStringToString(ui.betLineEdit->text(), bet);
	string plays;
	QStringToString(ui.playsLineEdit->text(), plays);
	for (int counter = 0; counter < bet.length(); counter++) {
		if (charToInt(bet[counter]) == -1) {
			ui.messageLabel->setText("<h2><font color=red>Error: Invalid Character In Bet Amount</font></h2>");
			return false;
		}
	}
	
	if (StringToInteger(bet) * StringToInteger(plays) > playerStats.totalMoney) {
		ui.messageLabel->setText("<h2><font color=red>Error: Not Enough Funds To Cover Your Bet</font></h2>");
		return false;
	}
	
	if (bet.length() == 0) {
		ui.messageLabel->setText("<h2><font color=red>Error: No Bet Specified</font></h2>");
		return false;
	}
	return true;
	
}

bool Slots::checkNumPlays() {
	string plays;
	QStringToString(ui.playsLineEdit->text(), plays);
	for (int counter = 0; counter < plays.length(); counter++) {
		if (charToInt(plays[counter]) == -1) {
			ui.messageLabel->setText("<h2><font color=red>Error: Invalid Character In Play Amount</font></h2>");
			return false;
		}
	}
	
	
	if (plays.length() == 0) {
		ui.messageLabel->setText("<h2><font color=red>Error: Number Of Plays Not Specified</font></h2>");
		return false;
	}
	return true;
}

void Slots::changeAllLCDNumberColors() {
	QPalette myPalette;
	myPalette = ui.lcdNumber9->palette();
	myPalette.setColor(QPalette::Light, Qt::black);
	ui.lcdNumber1->setPalette(myPalette);
	ui.lcdNumber1->repaint();
	ui.lcdNumber2->setPalette(myPalette);
	ui.lcdNumber2->repaint();
	ui.lcdNumber3->setPalette(myPalette);
	ui.lcdNumber3->repaint();
	ui.lcdNumber4->setPalette(myPalette);
	ui.lcdNumber4->repaint();
	ui.lcdNumber5->setPalette(myPalette);
	ui.lcdNumber5->repaint();
	ui.lcdNumber6->setPalette(myPalette);
	ui.lcdNumber6->repaint();
	ui.lcdNumber7->setPalette(myPalette);
	ui.lcdNumber7->repaint();
	ui.lcdNumber8->setPalette(myPalette);
	ui.lcdNumber8->repaint();
	ui.lcdNumber9->setPalette(myPalette);
	ui.lcdNumber9->repaint();
}

void Slots::changeLCDNumberToWinColor(int number) {
	QPalette myPalette;
	myPalette = ui.lcdNumber9->palette();
	myPalette.setColor(QPalette::Light, Qt::green);
	switch (number) {
	case 1:
		ui.lcdNumber1->setPalette(myPalette);
		ui.lcdNumber1->repaint();
		break;
	case 2:
		ui.lcdNumber2->setPalette(myPalette);
		ui.lcdNumber2->repaint();
		break;
	case 3:
		ui.lcdNumber3->setPalette(myPalette);
		ui.lcdNumber3->repaint();
		break;
	case 4:
		ui.lcdNumber4->setPalette(myPalette);
		ui.lcdNumber4->repaint();
		break;
	case 5:
		ui.lcdNumber5->setPalette(myPalette);
		ui.lcdNumber5->repaint();
		break;
	case 6:
		ui.lcdNumber6->setPalette(myPalette);
		ui.lcdNumber6->repaint();
		break;
	case 7:
		ui.lcdNumber7->setPalette(myPalette);
		ui.lcdNumber7->repaint();
		break;
	case 8:
		ui.lcdNumber8->setPalette(myPalette);
		ui.lcdNumber8->repaint();
		break;
	case 9:
		ui.lcdNumber9->setPalette(myPalette);
		ui.lcdNumber9->repaint();
		break;
	}
}


void QStringToString(QString original, string &final) {
	final = "";
	for (int counter = 0; counter < original.length(); counter++) {
		final += original[counter].toAscii();
	}
}

int StringToInteger(string original) {
	int size = original.size();
	int value = 0;
	for (int counter = 0; counter < size; counter++) {
		value += charToInt(original[counter]) * pow(double(10), double(size - counter -1));
	}
	return value;
}

int charToInt(char character) {
	switch (character) {
	case '0':
		return 0;
	case '1':
		return 1;
	case '2':
		return 2;
	case '3':
		return 3;
	case '4':
		return 4;
	case '5':
		return 5;
	case '6':
		return 6;
	case '7':
		return 7;
	case '8':
		return 8;
	case '9':
		return 9;
	default:
		return -1;
	}
	return -1;
}

string integerToString(int value) {
	ostringstream o;
	o << value;
	return o.str();
}
