/**********************************************************************
 *
 *   FreeDoko a Doppelkopf-Game
 *    
 *   Copyright (C) 2001-2004  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_GAMEPLAY_HEADER
#define CLASS_GAMEPLAY_HEADER

#include "../os/os.h"

class Card;
class Hand;
class Game;
class Player;

// The gameplay, saved as actions
class Gameplay : public OS {
  public:
    class Action {
      public:
	enum Type {
	  POVERTY_SHIFT,
	  POVERTY_RETURNED,
	  ANNOUNCEMENT,
	  SWINES,
	  HYPERSWINES,
	  CARD_PLAYED,
	  TRICK_CLOSED,
	  MARRIAGE,
	  GENSCHER
	}; // enum Type
	union Data {
	  Announcement announcement;
	  Card* card;
	  unsigned partner;
	  vector<Card>* cards;
	}; // union Data

      public:
	// 'POVERTY_SHIFT', 'POVERTY_RETURNED'
	Action(Type const type,
	       unsigned const playerno,
	       Hand const& hand);
	// 'ANNOUNCEMENT'
	Action(Type const type,
	       unsigned const playerno,
	       Announcement const announcement);
	// 'SWINES', 'HYPERSWINES'
	Action(Type const type,
	       unsigned const playerno);
	// 'CARD_PLAYED'
	Action(Type const type,
	       unsigned const playerno,
	       Card const& card);
	// 'TRICK_CLOSED'
	Action(Type const type,
	       Trick const& trick);
	// 'GENSCHER', 'MARRIAGE'
	Action(Type const type,
	       unsigned const playerno,
	       unsigned const partner);

	// destructor
	~Action();

	// copy constructor
	Action(Action const& action); // default
	// copy operator
	Action& operator=(Action const& action); // default
	

	// write the action into the output stream
	ostream& write(ostream& ostr) const;

      public:
	Type type; // which action
	unsigned player; // which player has made the action
	Data data; // data of the 

      private: // unused
	Action();
    }; // class Action
  public:
    Gameplay();
    ~Gameplay();

    // write the gameplay in the output stream
    ostream& write(ostream& ostr) const;

    // the parts of a game
    void game_open(Game const& game);
    void game_cards_distributed();
    void game_redistribute();
    void game_start();
    void game_close();

    void trick_close();
    // the card is played
    void card_played(HandCard const& card);
    // 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);

    // 'player' shifts 'cardno' cards
    void poverty_shift(Player const& player, unsigned const cardno);
    // the player 'player' has accepted the poverty trumps
    // and has returned 'cardno' cards with 'trumpno' trumps
    void poverty_take_accepted(Player const& player,
			       unsigned const cardno,
			       unsigned const trumpno);

    // the marriage partner has found a bride
    void marriage(Player const& bridegroom, Player const& bride);
    // a player has announced a genscher
    void genscher(Player const& genscher, Player const& partner);

  private:
    PRIV_VAR_R(unsigned, seed);
    PRIV_VAR_R(GameType, gametype);
    PRIV_VAR_R(unsigned, soloplayer);
    PRIV_VAR_R(vector<Hand>, hands);
    PRIV_VAR_R(list<Action>, actions);

  private: // not implemented
    Gameplay(Gameplay const&);
    Gameplay& operator=(Gameplay const&);
}; // class Gameplay

string name(Gameplay::Action::Type const type);
ostream& operator<<(ostream& ostr, Gameplay::Action::Type const type);
ostream& operator<<(ostream& ostr, Gameplay::Action const& action);
ostream& operator<<(ostream& ostr, Gameplay const& gameplay);

#endif // #ifndef CLASS_GAMEPLAY_HEADER
