/**********************************************************************
 *
 *   FreeDoko a Doppelkopf-Game
 *    
 *   Copyright (C) 2001-2006  by Diether Knof and Borg Enders
 *
 *   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 can find this license in the file 'gpl.txt'.
 *
 *   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
 *
 *  Contact:
 *    Diether Knof dknof@gmx.de
 *    Borg Enders  borg@borgsoft.de
 *
 *********************************************************************/

#ifndef CLASS_CARDS_INFORMATION_HEADER
#define CLASS_CARDS_INFORMATION_HEADER

#include "../../card/card.h"

#include "../../basistypes.h"
#include "../../card/hand.h"
#include "../../card/card_counter.h"

#include "../../game/exception.h"

class Player;
class Ai;
class Game;

#ifndef RELEASE
// card of interest, for debugging
#define COI Card(Card::CLUB, Card::ACE)
#endif

/**
 ** Contains and analyses the information, who has played which card
 ** and gives the information which cards a player can have.
 **
 ** @author	Diether Knof
 **/
class CardsInformation {
  friend bool operator==(CardsInformation const&, CardsInformation const&);

  public:
  class OfPlayer;

  public:
  // constructor
  CardsInformation(Ai const& player);
  // copy constructor
  CardsInformation(CardsInformation const& cards_information);
  // copy operator
  CardsInformation& operator=(CardsInformation const& cards_information);
  // destructor
  ~CardsInformation();


  // writes the information in 'ostr'
  void write(ostream& ostr) const;

  // reset all informations
  void reset();
  // recalcs all information
  void recalc();


  // the information of single players
  OfPlayer const& of_player(Player const& player) const;
  OfPlayer const& of_player(unsigned const playerno) const;

  // hand with all possible cards of the player
  Hand possible_hand(Player const& player) const;
  // the estimated hand for the player
  Hand estimated_hand(Player const& player) const;


  // the highest remaining trump
  HandCard highest_remaining_trump() const;
  // the highest remaining trump of the other players
  HandCard highest_remaining_trump_of_others() const;
  // whether there exists a higher card on the other hands
  bool higher_card_exists(HandCard const& card) const;



  // the corresponding game
  Game const& game() const;


  // some settings

  // set the player
  void set_player(Ai const& player);
  // set the hand of the player
  void set_hand(Player const& player, Hand const& hand);


  // intern methods

  // updates the information of the card
  void update_information(Card const& card);
  // updates the information of all cards
  void update_information_all();
  // updates 'can have' according to 'remaining cards'
  void update_remaining_cards();


  // the number of forgotten tricks
  unsigned forgotten_tricks_no() const;
  // the number of forgotten cards
  unsigned forgotten_cards_no() const;
  // how many cards have been played in total in the game
  unsigned played_cards_no() const;
  // how many of 'card' have been played
  unsigned played(Card const& card) const;
  // how many cards of 'tcolor' have been played
  unsigned played(Card::TColor const& tcolor) const;


  // the information from the game

  // the game starts
  void game_start();
  // the trick is opened
  void trick_open(Trick const& trick);
  // the card is played
  void card_played(HandCard const& card);
  // the card is played
  void card_played(HandCard const& card, Trick const& trick);
  // an announcement is made
  void announcement_made(Announcement const& announcement,
			 Player const& player);
  // the player has swines
  void swines_announced(Player const& player);
  // the player has hyperswines
  void hyperswines_announced(Player const& player);
  // a player has announced a genscher
  void genscher(Player const& genscher, Player const& partner);

  private:
#ifdef DKNOF
  public:
#endif
  // checks the data for error
  bool self_check() const;

  private:
  // the corresponding player
  PRIV_VAR_CP_R(Ai, player);
  // the information for a specific player
  vector<OfPlayer> of_player_;
  // how many cards have been played
  CardCounter played_;
  // whether we are in a recalcing
  PRIV_VAR_R(bool, in_recalcing);

  private: // unused
  CardsInformation();
}; // class CardsInformation

// writes the cards information into the output stream
ostream& operator<<(ostream& ostr,
		    CardsInformation const& cards_information);
// compares two cards informations
bool operator==(CardsInformation const& cards_information_a,
		CardsInformation const& cards_information_b);
// compares two cards informations
bool operator!=(CardsInformation const& cards_information_a,
		CardsInformation const& cards_information_b);

#endif // #ifndef CLASS_CARDS_INFORMATION_HEADER
