/**********************************************************************
 *
 *   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
 *
 *********************************************************************/

#include "constants.h"

#include "gameplay_action.h"
#include "gameplay_actions.h"

#include "../card/trick.h"
#include "../card/hand.h"
#include "../player/player.h"
#include "../misc/translations.h"

#include "../utils/string.h"


/**
 ** returns an action type determined by the line
 **
 ** @param	line	line with the action data
 ** @param	istr	input stream (behind the line)
 **
 ** @return	action corresponding to the line
 **		(to be freed)
 **
 ** @author	Diether Knof
 ** 
 ** @version	0.6.8
 **/
GameplayAction*
GameplayAction::new_(string const& line, istream& istr)
{
  if (line.empty())
    return NULL;

#ifndef OUTDATED
  string const keyword
    = ( (std::find(line.begin(), line.end(), ':')
	 != line.end())
       ? string(line.begin(),
		std::find(line.begin(), line.end(), ':'))
       : (  (std::find(line.begin(), line.end(), '=')
	     != line.end())
	  ? string(line.begin(),
		   std::find(line.begin(), line.end(), '='))
	  : line
	 )
      );
#else
  string const keyword
    = (  (std::find(line.begin(), line.end(), '=')
	  != line.end())
       ? string(line.begin(),
		std::find(line.begin(), line.end(), '=') - 1)
       : line
      );
#endif

#ifndef OUTDATED
  if (keyword == "Marriage")
    return new Marriage(line);
  else if (keyword == "Genscher")
    return new Genscher(line);
  else if (keyword == "Poverty Shift")
    return new PovertyShift(line);
  else if (keyword == "Poverty Returned")
    return new PovertyReturned(line);
  else if (keyword == "Poverty Denied By All")
    return new PovertyDeniedByAll(line);
  else if (keyword == "Announcement")
    return new Announcement(line);
  else if (keyword == "Swines")
    return new Swines(line);
  else if (keyword == "Hyperswines")
    return new Hyperswines(line);
  else if (keyword == "Played")
    return new CardPlayed(line);
  else if (keyword == "Trick full")
    return new TrickFull(line, istr);
#endif

  if (keyword == ::name(MARRIAGE))
    return new Marriage(line);
  else if (keyword == ::name(GENSCHER))
    return new Genscher(line);
  else if (keyword == ::name(POVERTY_SHIFT))
    return new PovertyShift(line);
  else if (keyword == ::name(POVERTY_RETURNED))
    return new PovertyReturned(line);
  else if (keyword == ::name(POVERTY_DENIED_BY_ALL))
    return new PovertyDeniedByAll(line);
  else if (keyword == ::name(ANNOUNCEMENT))
    return new Announcement(line);
  else if (keyword == ::name(SWINES))
    return new Swines(line);
  else if (keyword == ::name(HYPERSWINES))
    return new Hyperswines(line);
  else if (keyword == ::name(CARD_PLAYED))
    return new CardPlayed(line);
  else if (keyword == ::name(TRICK_FULL))
    return new TrickFull(line, istr);

  return NULL;
} // static GameplayAction* GameplayAction::new_(string line, istream& istr)

/**
 ** constructor
 **
 ** @param	type		action type
 ** @param	playerno	player who has made the action
 ** @param	hand		hand of the action
 **
 ** @return	-
 **
 ** @author	Diether Knof
 ** 
 ** @version	0.6.8
 **/
GameplayAction::GameplayAction(Type const type,
		       unsigned const playerno) :
  type(type),
  player(playerno)
{
} // GameplayAction::Action(Type type, unsigned playerno)

/**
 ** destructor
 **
 ** @param	-
 **
 ** @return	-
 ** 
 ** @author	Diether Knof
 **
 ** @version	0.6.8
 **/
GameplayAction::~GameplayAction()
{
  return ;
} // GameplayAction(Type type, unsigned playerno, Hand hand)

/**
 ** copy constructor
 **
 ** @param	action	action to copy
 **
 ** @return	-
 **
 ** @author	Diether Knof
 ** 
 ** @version	0.6.8
 **/
GameplayAction::GameplayAction(GameplayAction const& action) :
  type(action.type),
  player(action.player)
{
  return ;
} // GameplayAction::GameplayAction(GameplayAction action)

/**
 ** copy constructor
 **
 ** @param	action	action to copy
 **
 ** @return	-
 **
 ** @author	Diether Knof
 ** 
 ** @version	0.6.8
 **/
GameplayAction::GameplayAction&
GameplayAction::operator=(GameplayAction const& action)
{
  this->type = action.type;
  this->player = action.player;

  return *this;
} // GameplayAction& operator=(GameplayAction action)

/**
 ** -> result
 **
 ** @param	-
 **
 ** @return	a translation representing the data
 ** 
 ** @author	Diether Knof
 **
 ** @version	0.7.1
 **/
Translator::Translation
GameplayAction::data_translation() const
{
  return ::translation("");
} // virtual Translator::Translation GameplayAction::data_translation() const

/**
 ** -> result
 **
 ** @param	type	action tye
 **
 ** @return	name of the action type
 ** 
 ** @author	Diether Knof
 **
 ** @version	0.6.8
 **/
string
name(GameplayAction::Type const type)
{
  switch(type) {
  case GameplayAction::MARRIAGE:
    return "marriage";
  case GameplayAction::GENSCHER:
    return "genscher";
  case GameplayAction::POVERTY_SHIFT:
    return "poverty shift";
  case GameplayAction::POVERTY_RETURNED:
    return "poverty returned";
  case GameplayAction::POVERTY_DENIED_BY_ALL:
    return "poverty denied by all";
  case GameplayAction::ANNOUNCEMENT:
    return "announcement";
  case GameplayAction::SWINES:
    return "swines";
  case GameplayAction::HYPERSWINES:
    return "hyperswines";
  case GameplayAction::CARD_PLAYED:
    return "card played";
  case GameplayAction::TRICK_FULL:
    return "trick full";
  } // switch(type)

  DEBUG_ASSERTION(false,
		  "name(GameplayAction::Type type):\n"
		  "  unknown type '" << static_cast<int>(type) << "'");

  return "";
} // string name(GameplayAction::Type const type)

/**
 ** writes the type in the output stream
 **
 ** @param	ostr	output stream
 ** @param	type	action tye
 **
 ** @return	output stream
 ** 
 ** @author	Diether Knof
 **
 ** @version	0.6.8
 **/
ostream&
operator<<(ostream& ostr, GameplayAction::Type const type)
{
  ostr << ::name(type);
  return ostr;
} // ostream& operator<<(ostream& ostr, GameplayAction::Type type)

/**
 ** writes the action in the output stream
 **
 ** @param	ostr	output stream
 ** @param	action	action
 **
 ** @return	output stream
 ** 
 ** @author	Diether Knof
 **
 ** @version	0.6.8
 **/
ostream&
operator<<(ostream& ostr, GameplayAction const& action)
{
  action.write(ostr);

  return ostr;
} // ostream& operator<<(ostream& ostr, GameplayAction action)
