/*
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <stdio.h>
#include <stdlib.h>

// QT includes
#include <qlabel.h>
#include <qtimer.h>
#include <qpainter.h>
#include <qtooltip.h>
#include <qlayout.h>

// KDE includes
#include <kmessagebox.h>
#include <kapplication.h>
#include <kglobal.h>
#include <kstandarddirs.h>
#include <kdebug.h>
#include <kconfig.h>
#include <klocale.h>
#include <kaudioplayer.h>
#include <kcarddialog.h>

// own includes
#include "betbox.h"
#include "kpaint.h"
#include "optionsdlg.h"
#include "newgamedlg.h"
#include "player.h"
#include "playerbox.h"
#include "version.h"
#include "kpoker.h"
#include "defines.h"

CardImages *cardImage;

int* Player::cardHelp = 0;

kpok::kpok(QWidget *parent, const char *name) : QWidget(parent, name)
{
	QString version;

	lastHandText = "";

        version = kapp->caption() + " " + KPOKER_VERSION;
	setCaption( version );

	mOptions = 0;
	newGameDlg = 0;
	playerBox = 0;
	adjust = false;

	initSomeStuff();
	initSound();

	if (!readEntriesAndInitPoker())
		exit(0);
}

kpok::~kpok()
{
 if (mOptions != 0) {
	if (player.count() + removedPlayers.count() > 1) {
		minBet = mOptions->getMinBet();
		maxBet = mOptions->getMaxBet();
	}
	drawDelay = mOptions->getDrawDelay();
//	cashPerRound = mOptions->getCashPerRound(); // NOT(!) configurable
 }

 KConfig* conf = kapp->config();
 conf->setGroup("General");
 conf->writeEntry("MaxBet", maxBet);
 conf->writeEntry("MinBet", minBet);
// conf->writeEntry("CashPerRound", cashPerRound);
 conf->writeEntry("DrawDelay", drawDelay);

 for (int i = 0; i < allPlayersNr; i++)
 	delete playerBox[i];
 delete[] playerBox;// necessary?
 delete[] allPlayers;
 delete[] done;
 delete mOptions;
 delete newGameDlg;
 player.clear();
 removedPlayers.clear();
}

void kpok::newGame()
{
 lastHandText = "";
 newGameDlg = new NewGameDlg(this);
 newGameDlg->hideReadingFromConfig();
 if (newGameDlg->exec()) {
	stopBlinking();
	stopDrawing();
	stopWave();
	int players = DEFAULT_PLAYERS;
	//delete the old values
	for (int i = 0; i < allPlayersNr; i++)
		delete playerBox[i];
	delete[] allPlayers;
	delete[] playerBox;// necessary?

	player.clear();
	removedPlayers.clear();

	players = newGameDlg->getPlayers();

	//most things will be done in initPoker
	initPoker(players);
	for (int unsigned i = 0; i < player.count(); i++){
		player.at(i)->setName(newGameDlg->name(i));
		playerBox[i]->setName();
		player.at(i)->setCash((newGameDlg->money() >= minBet) ? newGameDlg->money() : START_MONEY);
	}
	paintCash();
	delete newGameDlg;
	newGameDlg = 0;
	drawButton->setText(i18n("&Draw"));
	drawButton->setEnabled(true);
 }
 else {
	delete newGameDlg;
	newGameDlg = 0;
//continue current game
 }

}

void kpok::newRound()
{
 bool removedPlayersIsEmpty = true;
 bool onePlayerGame = false;
 playerBox[0]->setHeldEnabled(false);

 if (removedPlayers.count() > 0)
	removedPlayersIsEmpty = false;
 int players = player.count() + removedPlayers.count();
 if (players == 1)
	onePlayerGame = true;

 readOptions(); // maybe some options have changed so check em
 player.clear();
 removedPlayers.clear();

 if (allPlayers[0].getCash() < minBet)
	noMoney();
 else {
	 for (int i = 0; i < players; i++) {
		if (allPlayers[i].getCash() >= minBet)
			player.append(&allPlayers[i]);
		else
			removePlayerFromRound(&allPlayers[i]);
 	}
 }

 if (player.count() == 1 && !onePlayerGame)
	switchToOnePlayerRules();

 pot = 0;
 blinkingBox = 0;
 wonLabel->hide();
 stopBlinking();
 stopWave();

 for (int unsigned i = 0; i < player.count(); i++)
 	player.at(i)->newRound();

 // we are beginning a new round so every card is available
 for (int i = 0; i < highestCard; i++)
 	done[i] = false;
 drawAllDecks();
 playerBox[0]->showHelds(false);

 //draw first cards of the round
 bool skip[CARDS];
 for (int i = 0; i < CARDS; i++)
 	skip[i] = false;

 for (int unsigned i = 0; i < player.count(); i++)
	drawCards(player.at(i), skip, done);

 if(player.count() > 1) {
	findHumanPlayer()->changeBet(minBet);
 	pot += minBet;
	betBox->show();
 }
 else {
 	player.at(0)->changeBet(cashPerRound);
	betBox->hide();
 }

 paintCash();

 drawTimer->start(drawDelay, TRUE);
}

void kpok::bet()
{
// the players will bet, now. player 1 (the human one ;-)) has already bet using the betBox
// ALL players (except player 1 who has already had) will get a chance to raise the value
// if nobody raises further that player will not get another chance, else he will

 bool raised = false;
 int oldMustBet = 0;
 if (getStatus() == statRaise)
 	oldMustBet = currentMustBet;

 if (getStatus() == statBet || getStatus() == statRaise) {
 	currentMustBet = findHumanPlayer()->getCurrentBet(); // ??? ->maybe bad in raise phase
//first bet as usual
	 for (int unsigned i = 0; i < player.count(); i++) {
		if (!player.at(i)->getHuman()) {
			int playerBet = 0;
			if (getStatus() == statBet) // first bet phase
				playerBet = player.at(i)->bet(currentMustBet);
			else if (getStatus() == statRaise) // 2nd bet phase
				playerBet = player.at(i)->raise(currentMustBet);
			if (playerBet < currentMustBet) { // playerBet == 0
				removePlayerFromRound(player.at(i));
				if (getStatus() == statBet) pot += minBet;
				i--;
			}
			else {
				if (playerBet > currentMustBet)
					raised = true;
				currentMustBet = playerBet;
				pot += (currentMustBet - oldMustBet);
			}
		}
	 }
 }

// check if the bet has been raised
else if (getStatus() == statContinueBet || getStatus() == statContinueRaise) {
	paintCash();//?
	for (int unsigned i = 0; i < player.count(); i++) {
		if (player.at(i)->getCurrentBet() < currentMustBet &&
			player.at(i)->getHuman()) { // human player
				removePlayerFromRound(player.at(i));
				i--;
		}
/* else if (player.at(i)->getCurrentBet() < currentMustBet) {
// computer player -> not possible, yet: human player is not allowed to raise!
			int oldBet = player.at(i)->getCurrentBet(); int playerBet = 0; if (getStatus() == statBet) // 1st bet phase playerBet = player.at(i)->bet(currentMustBet); else if (getStatus() == statRaise) // 2nd bet phase playerBet = player.at(i)->raise(currentMustBet); if (playerBet < currentMustBet) { removePlayerFromRound(player.at(i)); i--; } else { if (playerBet > currentMustBet) raised = true; currentMustBet = playerBet; pot += playerBet - oldBet; } }*/
	}
 }

 paintCash();


 oldBet_raise = findHumanPlayer()->getCurrentBet(); // used by out() only
 if (getStatus() == statBet || getStatus() == statRaise) {
	if (raised) {
		if (getStatus() == statBet)
			setStatus(statContinueBet);
		else
			setStatus(statContinueRaise);

		if (adjust)
			adjustBet();
		else
			out(); // not necessary
		betBox->setEnabled(true);
		betBox->beginRaise();
		if (adjust)
			emit statusBarMessage(i18n("Clicking on draw means you adjust your bet"));
		else
			emit statusBarMessage(i18n("Clicking on draw means you are out"));
	}
	else {
		if (getStatus() == statBet)
			setStatus(statExchange);
		else
			setStatus(statSee);
	}
 }
 else if (getStatus() == statContinueBet && !raised) {
	emit clearStatusBar();
//	weWillAdjustLabel->hide();
	betBox->stopRaise();
	setStatus(statExchange);
 }
 else if (getStatus() == statContinueRaise && !raised) {
	emit clearStatusBar();
//	weWillAdjustLabel->hide();
	betBox->stopRaise();
	setStatus(statSee);
 }


// check if player 1 is out -> for players > 2
// TODO: maybe if (!player.contains(humanPlayer))
// {exchangeCards(); bet(); displayerWinner_computer();return;}


// don't continue game if player 1 is alone
// TODO: port to players > 2
// this is ONLY working for players <= 2
 if (removedPlayers.count() >= 1 && player.count() == 1)
	displayWinner_Computer(player.at(0), true);
}

void kpok::out()
{
// weWillAdjustLabel->hide();
 emit clearStatusBar();
 pot += (oldBet_raise - findHumanPlayer()->getCurrentBet());
 findHumanPlayer()->changeBet(oldBet_raise - findHumanPlayer()->getCurrentBet());
 paintCash();
 drawButton->setText(i18n("&Draw"));
}

void kpok::adjustBet()
{
// weWillAdjustLabel->hide();
 emit clearStatusBar();
 betChange(currentMustBet - findHumanPlayer()->getCurrentBet());
 paintCash();
}

void kpok::setSize(int players)
{
//FIXME
// is obsoleted by qlayouts
return ;
 int width = PLAYERBOX_WIDTH; // quit easy no?
 int height = players * PLAYERBOX_HEIGHT;
 if (players > 1)
	height += DISTANCE_FROM_2ND_BOX;
 else {
 	height += potLabel->height() + 10; // to see the potLabel
	height += drawButton->height() + 5; // to see the drawButton
 }
 height += 10;

 setFixedSize(width, height);
}

void kpok::initPoker(int players, Player* ownAllPlayers)
{
 allPlayersNr = players; //currently anly used for deleting

// read some defaults
 kapp->config()->setGroup("General");
 minBet = kapp->config()->readNumEntry("MinBet", MIN_BET);
 maxBet = kapp->config()->readNumEntry("MaxBet", MAX_BET);
// cashPerRound = kapp->config()->readNumEntry("CashPerRound", CASH_PER_ROUND); // NOT(!) configurable
 cashPerRound = CASH_PER_ROUND;
 drawDelay = kapp->config()->readNumEntry("DrawDelay", DRAWDELAY);

 blinkingBox = 0;
 setStatus(statDraw);
 currentMustBet = minBet;

// init the players first
// we use a QPtrList to access the players
 player.clear();
 removedPlayers.clear();
 if (ownAllPlayers == 0) {
	allPlayers = new Player[players];
	for (int i = 0; i < players; i++)
		player.append(&allPlayers[i]);
	player.at(0)->initCardHelp();
	player.at(0)->setHuman();
	player.at(0)->setName(i18n("You"));
	for (int unsigned i = 1; i < player.count(); i++) {
		player.at(i)->setName(QString("Computer %1").arg(i-1));
	}

 }
 else { // there has someone an own version of allPlayers so lets use it!
	allPlayers = &ownAllPlayers[0]; // I hope...
	for (int i = 0; i < players; i++)
		player.append(&allPlayers[i]);
 }

 for (int unsigned i = 0; i < player.count(); i++)
	player.at(i)->setBetDefaults(minBet, maxBet); // inform players how much they may bet

// make all labels / boxes / carwdidgets for ever player
 playerBox = new PlayerBox *[player.count()]; // not nice but more easy to use ;-)

 for (int unsigned i = 0; i < player.count(); i++) {
	playerBox[i] = new PlayerBox(i == 0, this);
	playerBox[i]->setLocalPlayer(player.at(i));
	if (i == 0)
		topLayout->insertWidget(0, playerBox[i]);
	else
		topLayout->addWidget(playerBox[i]);
	playerBox[i]->setName();
	playerBox[i]->hide();
	playerBox[i]->show();	// if it has been deleted and created again it
				// hasn't be shown correctly - hiding and
				// re-showing solves the problem

 }

// connects for player 1
 playerBox[0]->activateToggleHeld(); // make CardWidget::toggleHeld() work
 connect(playerBox[0], SIGNAL(toggleHeld()), this, SLOT(toggleHeld()));

// hide some things
 playerBox[0]->showHelds(false);
 wonLabel->hide();
 emit showClickToHold(false);
 if (player.count() > 1) {
	setHand(i18n("Nobody"), false);
 	betBox->show();
	betBox->setEnabled(false);
	potLabel->show();
 }
 else {
	setHand(i18n("Nothing"));
 	betBox->hide();
	potLabel->hide();
	playerBox[0]->onePlayerGame(cashPerRound);
 }

// some final inits
 drawStat = 0;
 waveActive = 0;
 fCount = 0;

// finally clear the pot and show the decks/cash - in one word: begin :-)
 pot = 0;
 drawAllDecks();
 for (int unsigned i = 0; i < player.count(); i++) {
	playerBox[i]->repaintCard();
 }
 paintCash();
 playerBox[0]->setHeldEnabled(false);


// setFixedSize(sizeHint());
}

void kpok::paintCash()
{
 for (int unsigned i = 0; i < player.count(); i++) {
	playerBox[i]->paintCash();
	potLabel->setText(i18n("Pot: %1").arg(KGlobal::locale()->formatMoney(pot)));
 }

}

void kpok::updateLHLabel()
{
	if (lastHandText != "")
		setHand(lastHandText);
	else if (getPlayers() > 1)
		setHand(i18n("Nobody"), false);
	else
		setHand(i18n("Nothing"));
}

void kpok::setHand(const QString& newHand, bool lastHand)
{
 emit changeLastHand(newHand, lastHand);
 lastHandText = newHand;
}

void kpok::toggleHeld()
{
 if (getStatus() == statBet || getStatus() == statContinueBet)
      playSound("hold.wav");
}

void kpok::drawClick()
{
 if (!drawButton->isEnabled())
	return;

 if (getStatus() == statDraw) {// get new cards
	drawButton->setEnabled(false);
	betBox->setEnabled(false);
	newRound();
 }
 else if (getStatus() == statBet) { // bet
 	emit showClickToHold(false);
	//clickToHold->hide();

	bet();
	if (getStatus() == statExchange) {// should be set in bet()
		drawClick();
	}
 }
 else if (getStatus() == statContinueBet) { // continue bet
	bet();
	if (getStatus() == statExchange) {// should be set in bet()
		drawClick();
	}
 }
 else if (getStatus() == statExchange) { // exchange cards
	drawButton->setEnabled(false);
	playerBox[0]->setHeldEnabled(false);
	betBox->setEnabled(false);
 	bool skip[CARDS];
	for (int i = 0; i < CARDS; i++)
		skip[i] = false;

	for (int unsigned i = 0; i < player.count(); i++) {
		if (!player.at(i)->getHuman())
			player.at(i)->exchangeCards(skip);
		else {
		   	for (int i = 0; i < CARDS; i++) {
   				skip[i] = playerBox[0]->getHeld(i);
		   		if (!skip[i])
					playerBox[0]->paintDeck(i);
		   	}
		}
		drawCards(player.at(i), skip, done);
	}


   	if (playerBox[0]->getHeld(0))
		drawTimer->start(0, TRUE);
   	else
		drawTimer->start(drawDelay, TRUE);
   }
 else if (getStatus() == statRaise) { // raise
	setBetButtonEnabled(false);
	bet();

	if (getStatus() == statSee)//should be set in bet()->if no one has raised
		drawClick();
 }
 else if (getStatus() == statContinueRaise) {
	bet();
	if (getStatus() == statSee)
		drawClick();
 }
 else if (getStatus() == statSee)
	winner();
}

void kpok::drawCards(Player* p, bool skip[], bool done[])
{
 for (int i = 0; i < CARDS; i++) {
 	int got;
	if(!skip[i]) {
		do
			got = random.getLong(highestCard);
		while(done[got] == true);
		done[got] = true;
		p->takeCard(i, (got+1));
	}
 }
//TODO: REMOVE!!!
/*
 if (p->getName()=="You"){
p->takeCard(0, 52);
p->takeCard(1, 15);
p->takeCard(2, 10);
p->takeCard(3, 5);
p->takeCard(4, 4);
} else {
p->takeCard(0, 3);
p->takeCard(1, 2);
p->takeCard(2, 5);
p->takeCard(3, 6);
p->takeCard(4, 27);
} */
}

void kpok::displayWinner_Computer(Player* winner, bool othersPassed)
{
// which box?
 for (int unsigned i = 0; i < player.count() + removedPlayers.count(); i++) {
	if (&allPlayers[i] == winner)
		blinkingBox = i;
 }

 winner->setCash(winner->getCash() + pot);
 QString label;
 if (winner->getHuman())
   label = i18n("You won %1").arg(KGlobal::locale()->formatMoney(pot));
 else
   label = i18n("%1 won %2").arg(winner->getName()).arg(KGlobal::locale()->formatMoney(pot));
 wonLabel->setText(label);
 QFont waveFont;
 waveFont.setBold(true);
 waveFont.setPointSize(16);
 QFontMetrics tmp(waveFont);
 mWonWidget->setMinimumWidth(tmp.width(label) + 20);
 if (winner->getHuman()) {
  	playSound("win.wav");
 	wonLabel->hide();
	startWave();
 }
 else {
  	playSound("lose.wav");
	wonLabel->show();
 }

 pot = 0;
 setStatus(statDraw);
 drawButton->setEnabled(true);
 setHand(winner->getName(), false);
 paintCash();

//only start blinking if player 1 is not out
 if (player.contains(&allPlayers[0]) && !othersPassed)
 	startBlinking();

 drawButton->setText(i18n("&Draw"));
}

void kpok::showComputerCards()
{
// don't show cards of 'out' players

 for (int unsigned i = 0; i < player.count(); i++) {
	if(!player.at(i)->getHuman()){
		//TODO change:
		playerBox[i]->paintCard(drawStat);


	 	if (i == 1) //TODO : CHANGE!
			playSound("cardflip.wav");//perhaps in playerbox or even in  cardwidget
	}
 }

 if (drawStat == 4) {   // just did last card
 	drawButton->setEnabled(true);
 	drawStat = 0;
  } else { // only inc drawStat if not done with displaying
  	drawStat++;
	showComputerCards();
  }
}

void kpok::setBetButtonEnabled(bool enabled)
{ betBox->setEnabled(enabled); }

void kpok::drawCardsEvent()
{
 if (!playerBox[0]->getHeld(drawStat)) {
	playerBox[0]->paintCard(drawStat);

 	playSound("cardflip.wav");//maybe in playerbox or even in cardwidget
 }

 if (drawStat == 4) {   // just did last card
 	drawButton->setEnabled(true);
	betBox->setEnabled(true);
 	drawStat = 0;
 	if (getStatus() == statExchange) {
		if (player.count() == 1)
			result();
		else {
			//now give players the chance to raise
			drawButton->setText(i18n("&See!"));
			setStatus(statRaise);
		}
  	} else if (status == statDraw) {
		playerBox[0]->setHeldEnabled(true);
  		emit showClickToHold(true);
		//clickToHold->show();
//TODO:
  		setStatus(statBet);
 	}

  } else { // only inc drawStat if not done with displaying
  	drawStat++;
  	// look at next card and if it is held instantly call drawCardEvent again
  	if (playerBox[0]->getHeld(drawStat))
  		drawTimer->start(0,TRUE);
  	else
  		drawTimer->start(drawDelay,TRUE);
  }
}



void kpok::result()
{
 int testResult = player.at(0)->testHand();
 switch (testResult) {
 case 1 : if (player.at(0)->getFoundCard(0).cardType >= 17) {
		player.at(0)->cleanFoundCard();
		displayWin(i18n("Nothing"), 0); break;
  	}
  	displayWin(i18n("One Pair"), 5);  break;
  	case 2 : displayWin(i18n("Two Pairs"), 10); break;
  	case 3 : displayWin(i18n("3 of a kind"), 15); break;
  	case 4 : displayWin(i18n("Full House"), 40); break;
  	case 6 : displayWin(i18n("4 of a kind"), 125); break;
  	case 7 : displayWin(i18n("Straight"), 20); break;
  	case 8 : displayWin(i18n("Flush"), 25); break;
  	case 9 : displayWin(i18n("Straight Flush"), 250); break;
	case 10 : displayWin(i18n("Royal Flush"), 2000); break;

  	default: displayWin(i18n("Nothing"), 0); break;
 }

 startBlinking();
 setStatus(statDraw);

 if (player.at(0)->getCash() < cashPerRound)
	noMoney();
}

void kpok::noMoney()
{
  KMessageBox::sorry(0, i18n("You Lost"), i18n("Oops, you went bankrupt.\n"
			  "Starting a new game.\n"));
  newGame();
}

void kpok::startBlinking()
{ blinkTimer->start(650); }

void kpok::stopBlinking()
{
   blinkTimer->stop();
   blinkStat = 1;
   blinkingBox = 0;
}

void kpok::startWave()
{
   waveTimer->start(40);
   waveActive = true;
}

void kpok::stopWave()
{
   waveTimer->stop();
   fCount = -1; /* clear image */
   repaint ( FALSE );
   waveActive = false;
}

void kpok::stopDrawing()
{
    drawTimer->stop();
}

void kpok::waveTimerEvent()
{
   fCount = (fCount + 1) & 15;
   repaint( FALSE );
}

void kpok::bTimerEvent()
{
 if (blinking) {
	 if (blinkStat != 0) {
		playerBox[blinkingBox]->blinkOn();
	 	blinkStat=0;
	 } else {
		playerBox[blinkingBox]->blinkOff();
	 	blinkStat=1;
	 }
 }
}

void kpok::displayWin(const QString& hand, int cashWon)
{
 QString buf;

 setHand(hand);
 player.at(0)->setCash(player.at(0)->getCash() + cashWon);
 paintCash();

 if (cashWon) {
 	playSound("win.wav");
 	buf = i18n("You won %1!").arg(KGlobal::locale()->formatMoney(cashWon));
 } else {
 	playSound("lose.wav");
 	buf = i18n("Game Over"); // locale
 }
 wonLabel->setText(buf);

 if (!cashWon)
 	wonLabel->show();
 else {
 	wonLabel->hide();
 	startWave();
 }
}


void kpok::paintEvent( QPaintEvent *)
{
   /* This was shamelessy stolen from the "hello world" example coming with Qt
      Thanks to the Qt-Guys for doing such a cool example 8-)
   */


   if (!waveActive) {
      return;
   }

   QString t = wonLabel->text();
   wonLabel->hide();

   static int sin_tbl[16] = {
      0, 38, 71, 92, 100, 92, 71, 38,  0, -38, -71, -92, -100, -92, -71, -38};

   if ( t.isEmpty() ) {
      return;
   }

   QFont wonFont;
   wonFont.setPointSize(18);
   wonFont.setBold(true);

   QFontMetrics fm = QFontMetrics(wonFont);

   int w = fm.width(t) + 20;
   int h = fm.height() * 2;
   while (w > mWonWidget->width() && wonFont.pointSize() > 6) {// > 6 for emergency abort...
   	wonFont.setPointSize(wonFont.pointSize() - 1);
   	fm = QFontMetrics(wonFont);
	w = fm.width(t) + 20;
   	h = fm.height() * 2;
   }

   int pmx = mWonWidget->width() / 2 - w / 2;
   int pmy = 0;
//   int pmy = (playerBox[0]->x() + playerBox[0]->height() + 10) - h / 4;

   QPixmap pm( w, h );
   pm.fill( mWonWidget, pmx, pmy );

   if (fCount == -1) { /* clear area */
      bitBlt( mWonWidget, pmx, pmy, &pm );
      return;
   }

   QPainter p;
   int x = 10;
   int y = h/2 + fm.descent();
   unsigned int i = 0;
   p.begin( &pm );
   p.setFont( wonFont );
   p.setPen( QColor(0,0,0) );

   while ( i < t.length() ) {
      int i16 = (fCount+i) & 15;

      p.drawText( x, y-sin_tbl[i16]*h/800, QString(t[i]), 1 );
      x += fm.width( t[i] );
      i++;
   }
   p.end();

// 4: Copy the pixmap to the Hello widget
   bitBlt( mWonWidget, pmx, pmy, &pm );

}

void kpok::drawAllDecks()
{
 for (int unsigned i = 0; i < player.count(); i++) {
 	for (int unsigned i2 = 0; i2 < CARDS; i2++) {
  		player.at(i)->takeCard(i2, 0);
		playerBox[i]->paintCard(i2);
 	}
 }
}

void kpok::removePlayerFromRound(Player* removePlayer)
{
 removePlayer->setOut(true);
 removedPlayers.append(removePlayer);
 if (player.contains(removePlayer))
	player.remove(removePlayer);

 for (int unsigned i = 0; i < player.count() + removedPlayers.count(); i++)
	playerBox[i]->paintCash();
}

void kpok::switchToOnePlayerRules()
{
 KMessageBox::information(0, i18n("You are the only player with money!\n"
			"Switching to one player rules..."), i18n("You Won"));
 for (int unsigned i = 1; i < player.count() + removedPlayers.count(); i++) {
	playerBox[i]->hide();
 }
 removedPlayers.clear();
 betBox->hide();
 potLabel->hide();
 playerBox[0]->onePlayerGame(cashPerRound);
 setHand(i18n("Nothing"));
// drawButton->move(this->width() /2 - drawButton->width() /2, drawButton->y()+20);
// setFixedSize(PLAYERBOX_WIDTH, player.count() * PLAYERBOX_HEIGHT + 10 + 20 + drawButton->height()); // or the rest of the window will only be empty :-(
}

Player* kpok::findHumanPlayer()
{
 for (int unsigned i = 0; i < player.count(); i++) {
	if (player.at(i)->getHuman())
		return player.at(i);
 }
 return player.at(0);//error
}

bool kpok::readEntriesAndInitPoker()
{
 KConfig* conf = kapp->config();
 int players = DEFAULT_PLAYERS;
 Player* newPlayers = 0;

 conf->setGroup("NewGameDlg");
 bool showNewGameDlg = conf->readBoolEntry("showNewGameDlgOnStartup", false);
 bool aborted = false;
 bool oldGame = false;

 if (showNewGameDlg) {
	newGameDlg = new NewGameDlg(this);
	if (!newGameDlg->exec())
		return false; // exit game
 }

 if (!aborted && (!showNewGameDlg || showNewGameDlg &&
					newGameDlg->readFromConfigFile())) {
	//try starting an old game
	oldGame = loadGame();
	if (oldGame)
		return true;
 }

 if (!aborted && showNewGameDlg && !oldGame) {
 // don't use config file - just take the values from the dialog
 // (is also config - the dialog defaults are from config)
	players = newGameDlg->getPlayers();
	if (players <= 0)
		aborted = true;
	else {
		newPlayers = new Player[players];
		newPlayers[0].initCardHelp();
		newPlayers[0].setHuman();
	}

	for (int i = 0; i < players; i++) {
		newPlayers[i].setName(newGameDlg->name(i));
		newPlayers[i].setCash(newGameDlg->money());
	}
 }

 if (aborted || !showNewGameDlg && !oldGame) // user didn't say what he/she wants -> use standards
 	initPoker(players);
 else // whatever user said: we have already a 'newPlayers'
	initPoker(players, newPlayers);

 if (newGameDlg != 0) {
	delete newGameDlg;
	newGameDlg = 0;
 }

 return true;
}

void kpok::betChange(int betChange)
{
 Player* p = findHumanPlayer();

 switch(getStatus()){
	case statBet:
		if (p->getCurrentBet() + betChange >= minBet &&
			p->getCurrentBet() + betChange <= maxBet) {
			// bet at least minBet but not more than maxBet
	 		if (p->changeBet(betChange))
				pot += betChange;
		}
		break;
	case statRaise:
	case statContinueRaise:
	case statContinueBet:
		if (p->getCurrentBet() + betChange >= currentMustBet &&
			p->getCurrentBet() + betChange <= currentMustBet +
			maxBet) {
	 		if (p->changeBet(betChange))
				pot += betChange;
		}
		break;
	default:
		break;
 }

 paintCash();
}

void kpok::saveGame()
{
 kapp->config()->setGroup("Save");
 saveGame(kapp->config());
}

void kpok::saveGame(KConfig* conf)
{
// kdWarning() << "save game" << endl;
 int players = allPlayersNr;

 conf->writeEntry("players", players);
 conf->writeEntry("lastHandText", lastHandText);

 for (int i = 0; i < players; i++) {
	conf->writeEntry(QString("Name_%1").arg(i), allPlayers[i].getName());
	conf->writeEntry(QString("Human_%1").arg(i), allPlayers[i].getHuman());
	conf->writeEntry(QString("Cash_%1").arg(i), allPlayers[i].getCash());
 }
}
/*
void kpok::commandCallback(int id)
{

 switch (id) {
	case ID_NEWGAME:
	case ID_SAVEGAME:
	case ID_EXIT:
		break;

//	case ID_OPTIONS: slotPreferences(); break;
//	case ID_SOUND: setSound(!sound); break;
//	case ID_BLINKING: setBlinking(!blinking); break;
//	case ID_ADJUST: setAdjust(!adjust); break;
 }
}
*/
void kpok::toggleSound() { setSound(!sound); }
void kpok::toggleBlinking() { setBlinking(!blinking); }
void kpok::toggleAdjust() { setAdjust(!adjust); }

void kpok::slotPreferences()
{
 if ( mOptions==0 )
        mOptions = new OptionsDlg(this, 0, player.count() + removedPlayers.count());
 if (player.count() + removedPlayers.count() > 1)
	mOptions->init(drawDelay, maxBet, minBet);
 else
	mOptions->init(drawDelay, cashPerRound);
 if (!mOptions->exec()) {
	delete mOptions;
	mOptions = 0;
 }
}

void kpok::setAdjust(bool ad)
{
 adjust = ad;

//update guessed money statusbar if we currently are in need of adjust
 if (getStatus() == statContinueBet || getStatus() == statContinueRaise) {
	if (adjust)
		adjustBet();
	else
		out();
 }
}

bool kpok::initSound()
{
 sound = true;
 return true;
}

void kpok::playSound(const QString &soundname)
{
  if (sound)
    KAudioPlayer::play(locate("data", QString("kpoker/sounds/")+soundname)); }

void kpok::setSound(bool s)
{
  sound = s;
}

void kpok::readOptions()
{
 if (mOptions != 0) {
	if (player.count() + removedPlayers.count() > 1) {
		minBet = mOptions->getMinBet();
		maxBet = mOptions->getMaxBet();
		for (int unsigned i = 0; i < player.count(); i++)
			player.at(i)->setBetDefaults(minBet, maxBet); // inform players how much they may bet
	}
	drawDelay = mOptions->getDrawDelay();
//	kdDebug() << cashPerRound << endl;
//	cashPerRound = mOptions->getCashPerRound(); // NOT(!) configurable
	delete mOptions;
	mOptions = 0;
 }
}

bool kpok::loadGame()
{
 kapp->config()->setGroup("Save");
 return loadGame(kapp->config());
}

bool kpok::loadGame(KConfig* conf)
{
 int players = DEFAULT_PLAYERS;
 Player* newPlayers = 0;

 bool oldGame = false;

 // conf->setGroup("Save");
 players = conf->readNumEntry("players", -1);

 if (players > 0) {
 	newPlayers = new Player[players];
 	newPlayers[0].initCardHelp();

 	for (int i = 0; i < players; i++) {
 		QString buf = conf->readEntry(QString("Name_%1").arg(i),
							 "Player");
		newPlayers[i].setName(buf);
		bool human = conf->readBoolEntry(QString("Human_%1").arg(i),
							 false);
		if (human)
			newPlayers[i].setHuman(); // i == 0
		int cash = conf->readNumEntry(QString("Cash_%1").arg(i),
							 START_MONEY);
		newPlayers[i].setCash(cash);
	}
	oldGame = true;
	initPoker(players, newPlayers);
	// after initPoker because initPoker does a default initialization of lastHandText
	conf->setGroup("Save");
	lastHandText = conf->readEntry("lastHandText", "");
	return true;
 }
 else
	players = DEFAULT_PLAYERS;
 return false;
}

void kpok::exchangeCard1()
{ playerBox[0]->cardClicked(1); }
void kpok::exchangeCard2()
{ playerBox[0]->cardClicked(2); }
void kpok::exchangeCard3()
{ playerBox[0]->cardClicked(3); }
void kpok::exchangeCard4()
{ playerBox[0]->cardClicked(4); }
void kpok::exchangeCard5()
{ playerBox[0]->cardClicked(5); }

void kpok::slotCardDeck()
{
 kapp->config()->setGroup("General");
 QString deckPath = kapp->config()->readPathEntry("DeckPath", 0);
 QString cardPath = kapp->config()->readPathEntry("CardPath", 0);
 bool randomDeck, randomCardDir;

 if (KCardDialog::getCardDeck(deckPath, cardPath, this, KCardDialog::Both,
		&randomDeck, &randomCardDir) == QDialog::Accepted) { // TODO make selecting of cards possible
	loadDeck(deckPath);
	loadCards(cardPath);
	kapp->config()->writePathEntry("DeckPath", deckPath);
	kapp->config()->writeEntry("RandomDeck", randomDeck);
	kapp->config()->writePathEntry("CardPath", cardPath);
	kapp->config()->writeEntry("RandomCardDir", randomCardDir);

 }
}

void kpok::loadCards(QString cardDir)
{
 for (int i = 0; i < highestCard; i++) {
	QString card = KCardDialog::getCardPath(cardDir, i + 1);
	if (card.isEmpty() || !cardImage->cardP[i].load(card)) {
		if (!card.isEmpty())
			kdWarning() << "Could not load " << card << " trying default" << endl;
		card = KCardDialog::getCardPath(KCardDialog::getDefaultCardDir(), i+1);
		if (!cardImage->cardP[i].load(card)) {
			kdError() << "Could not load " << card << endl;
		}
	}
 }

 for (int unsigned i = 0; i < player.count(); i++) {
	playerBox[i]->repaintCard();
 }
}

void kpok::loadDeck(QString path)
{
 if (playerBox && blinking && (blinkStat == 0))
	bTimerEvent();

 if (!cardImage->deck.load(path)) {
	kdWarning() << "Could not load deck - loading default deck" << endl;
	path = KCardDialog::getDefaultDeck();
	if (!cardImage->deck.load(path))
		kdError() << "Could not load deck" << endl;
 }

 for (int unsigned i = 0; i < player.count(); i++) {
	playerBox[i]->repaintCard();
 }
}

#include "kpoker.moc"

