/*
 *     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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#ifndef PLAYER_H
#define PLAYER_H

#include <qstring.h>

/**
  * Used to save the foun cards while searching the winning cards (e.g. whe the player has one pair both cards while be in foundCards)
  * @short Help struct for searching winning cards
 **/
struct FoundCard {
  /**
    * The number of the card in the players hand (0 = first card)
   **/
	int cardNum;
	
	/**
  	* The type of the card 0 = deck, 1-4 = Ace and so on
	 **/
	int cardType;
};

class Player
{
public:
 Player();
 ~Player();

 /**
   * Calculates the money which the computer will bet
   *
   * use @ref betChange() for human players
   * @param bet The minimum bet that the player has to bet. probably the same as the bet the human player has bet before
   * @param mayRaise Specifies if the player may raise
   * @return The player's bet
  **/
 int bet(int bet, bool mayRaise = true);

 /**
   * Same as @ref bet() but should bet a little bit more if the cards are good enough (they were already exchanged)
  **/
 int raise(int raise);

 /**
   * This method changes the player's bet by betChange
   * @param Specifies the change
   * @return true if sucessful, false if not
  **/
 bool changeBet(int betChange);

 /**
   * Only used by computer players
   *
   * Calculates which cards shall be exchanged
   * @param skip[] Will be set true if the card shall be exchanged (if the 1st card shall be exchanged so skip[0] will be true)
  **/
 void exchangeCards(bool skip[]);

 /**
   * This method will return all cards to the pile which means that all cards will be set to 0 (=deck)
  **/
 void giveCardsBack();

 /**
   * Returns a card to the pile
   * @param cardNr specifies the card which will be returned to the pile
  **/
 void giveCardBack(int cardNr);

 /**
   * Begins a new round
  **/
 void newRound();

 /**
   * Sets the player's cash to newCash
   * @param newCash The new cash
  **/
 void setCash(int newCash) 		{ money = newCash; }

 /**
   * This makes the player human
  **/
 void setHuman()			{ human = true; }

 /**
   * Sets a new name
   * @param newName The new name of the player
  **/
 void setName(QString newName) 		{ name = newName; }

 /**
   * Informs the player that he is out (or is not out anymore)
   * @param newOut true if player is out or false if player is back to the game
  **/
 void setOut(bool newOut)		{ isOut = newOut; }

 /**
   * Takes a card
   * @param nr The number of the card (0 = first card)
   * @param value The card itself
  **/
 void takeCard(int nr, int value) 	{ card[nr] = value; }

 /**
   * Informs the player about new rules
   * @param min The minimum possible bet
   * @param max The maximum possible bet
  **/
 void setBetDefaults(int min, int max)	{ minBet = min; maxBet = max; }

 /**
   * @param cardNr The number of the card (0 = first card)
   * @return The card
  **/
 int getCard(int cardNr) const		{ return card[cardNr]; }

 /**
   * @return The money of the player
  **/
 int getCash() const			{ return money; }

 /**
   * @return How much the player has bet
  **/
 int getCurrentBet() const 		{ return currentBet; }

 /**
   * Returns the found card at nr
   *
   * The found cards specify the best cards the player has, e.g. if the player has one pair both cards will be found here
   * @param nr The number of the wanted founCard
   * @return The found card number nr
  **/
 FoundCard getFoundCard(int nr)	const	{ return foundCards[nr]; }

 /**
   * @return If the player is human or not
  **/
 bool getHuman() const			{ return human; }

 /**
   * @return The name of the player
  **/
 QString getName() const		{ return name; }

 /**
   * @return True if the player is out or false if not
  **/
 bool out()				{ return isOut; }

 /**
   * Adds all cards up
   *
   * Useful to get the winner if two or more players have e.g. one pair -> the one with the aces will win ;-)
   * @return The sum
  **/
 int addFoundCardsUp();

 /**
   * Cleans all found cards
   * 
   * That means that all cardTypes in the struct foundCards will be set 0
  **/
 void cleanFoundCard();

 /**
   * Searches for the best card which is not in foundCards
  **/
 int findBestButFoundCard();

 /**
   * This searches for the best card of the player
   * @return The best card
  **/
 int findBestCard();

 /**
   * This sorts the result generated by @ref testHand() a little bit to be used in games with more than one player
   * @return The points of the hand (a royal flush is e.g. 0, a best card is 500 + the best card)
  **/
 int sortedResult();

 /**
   * This test the cards of the player; searches for the result
   *
   * Used by @ref sortedResult() and in one player games
   * @return The result (10 = the best, 0 = nothing)
  **/
 int testHand(); 

 /**
   * Initializes the cardHelp[] - called only once
  **/
 static void initCardHelp(); 

protected:
 /**
   * This adds a card to the foundCards
   * @param cardNum The number of the card (where 0 = first card)
   * @param cardType The card itself
  **/
 void addFoundCard(int cardNum, int cardType);

 /**
   *
  **/
// int findCardTypes(int cardT[CARDS], int card);
 int findCardTypes(int *cardT, int card);

 /**
   * Tests if the player has a flush
   * @return True if the player has a flush false if not
  **/
 bool testFlush();

 /**
   * Tests if the player has a straight
   * @return 0 if no straight was detected, 1 if a straight was detected, 2 if the straight could be a royal flush (still need to do a @ref testFlush())
  **/
 int testStraight();

private:
 int *card;
 FoundCard *foundCards;
 QString name;
 int money;
 int currentBet;
 static int* cardHelp;
 bool human;
 bool isOut;
 int minBet;
 int maxBet;
};

#endif
