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

#include "constants.h"
#include "card.h"

/**********************************************************************
 *
 ** Card:Card()
 *
 ** Parameters: None
 *
 ** Result: None
 *
 ** Version: Alpha
 *
 ** Description: 
 **   initizializing of color NOCARDCOLOR and value NOCARDVALUE
 *
 **********************************************************************/

Card::Card() :
color_p(NOCARDCOLOR),
value_p(NOCARDVALUE)
{ 
  DEBUG_CALLING(INFO_CARD && INFO_INIT,"Card::Card()");
  DEBUG_RETURNING_N(INFO_CARD && INFO_INIT,"Card::Card()");
}

/**********************************************************************
 *
 ** Card:Card(Card const& c)
 *
 ** Parameters: 
 **   c:  Card
 *
 ** Result: None
 *
 ** Version: Alpha
 *
 ** Description: 
 **   initizializing of color and value as c
 *
 **********************************************************************/

Card::Card(Card const& c):
color_p(c.color()), 
value_p(c.value())
{
  DEBUG_CALLING(INFO_CARD && INFO_INIT,"Card::Card(c)");

  DEBUG_RETURNING_N(INFO_CARD && INFO_INIT,"Card::Card(c)");
}

/**********************************************************************
 *
 ** Card:Card(Color c, Value v)
 *
 ** Parameters: 
 **   c: Color of to be created Card
 **   v: Value of to be created Card
 *
 ** Result: None
 *
 ** Version: Alpha
 *
 ** Description: 
 **   initizializing of color with c and of value with v
 *
 **********************************************************************/

Card::Card(Color const c, Value const v):
color_p(c), 
value_p(v)
{
  DEBUG_CALLING(INFO_CARD && INFO_INIT,"Card::Card(c,v)");
  
  if ((color() == NOCARDCOLOR) || (value() == NOCARDVALUE))
    color_p = NOCARDCOLOR, value_p = NOCARDVALUE;

  DEBUG_RETURNING_N(INFO_CARD && INFO_INIT,"Card::Card(c,v)");
}

/**********************************************************************
 *
 ** Card:Card(unsigned const color_u, unsigned const value_u)
 *
 ** Parameters:	color_u	- number of the color
 *		value_u	- number of the value
 *
 ** Result:	-
 *
 ** Version:	0.4.2
 *
 ** Description:	constructor
 *
 **********************************************************************/

Card::Card(unsigned const color_u, unsigned const value_u) :
color_p(NOCARDCOLOR), 
value_p(NOCARDVALUE)
{
  DEBUG_CALLING(INFO_CARD && INFO_INIT,"Card::Card(c,v)");

  switch(color_u) {
  case 0:
    this->color_p = DIAMOND;
    break;
  case 1:
    this->color_p = HEART;
    break;
  case 2:
    this->color_p = SPADE;
    break;
  case 3:
    this->color_p = CLUB;
    break;
  default:
    DEBUG_ASSERTION(false,
		    "Card::Card(unsigned color_u, unsigned value_u):\n"
		    "  invalid 'color_u'");
    break;
  } // switch(color_u)

  switch(value_u) {
  case 0:
    this->value_p = NINE;
    break;
  case 1:
    this->value_p = JACK;
    break;
  case 2:
    this->value_p = QUEEN;
    break;
  case 3:
    this->value_p = KING;
    break;
  case 4:
    this->value_p = TEN;
    break;
  case 5:
    this->value_p = ACE;
    break;
  default:
    DEBUG_ASSERTION(false,
		    "Card::Card(unsigned color_u, unsigned value_u):\n"
		    "  invalid 'value_u'");
    break;
  } // switch(value_u)

  if ((color() == NOCARDCOLOR)
      || (value() == NOCARDVALUE)) {
    color_p = NOCARDCOLOR;
    value_p = NOCARDVALUE;
  }

  DEBUG_RETURNING(VOID,
		  INFO_CARD && INFO_INIT,
		  "Card::Card(c,v)");
} // Card::Card(unsigned const color_u, unsigned const value_u)

/**
 **
 ** Konstruktor:
 ** reads 'color' and 'value' from 'name'
 **
 ** @param	name	the card name
 **
 ** @return	-
 **
 ** @version	0.5.2
 **
 ** @author	Diether Knof
 **   
 **/
Card::Card(string const& name) :
color_p(NOCARDCOLOR), 
value_p(NOCARDVALUE)
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
		"Card::Card(name)");

  istringstream istr(name);

  istr >> *this;

  DEBUG_RETURNING(VOID,
		  INFO_CARD && INFO_VALUE,
		  "Card::Card(name)");
} // Card::Card(string const& name)



/**********************************************************************
 *
 ** Card::~Card()
 *
 ** Parameters: None
 *
 ** Result: None
 *
 ** Version: Alpha
 *
 ** Description: 
 **   Destructor for Card
 *
 **********************************************************************/
Card::~Card()
{
  DEBUG_CALLING(INFO_CARD && INFO_INIT,"Card::~Card()");
  DEBUG_RETURNING_N(INFO_CARD && INFO_INIT,"Card::~Card()");
}

/**
 **
 ** copy operator
 **
 ** @param	card	card to copy
 **
 ** @return	copy of the card
 **
 ** @version	0.5.4
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 **/
Card&
Card::operator=(Card const& card)
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
		"Card::operator=(Card const& card)");

  this->color_p = card.color();
  this->value_p = card.value();

  DEBUG_RETURNING(*this,
		  INFO_CARD && INFO_VALUE,
		  "Card::operator=(Card const& card)");
} // Card& Card::operator=(Card const& card)

/**
 **
 ** read the card from the stream
 **
 ** @param	istr	stream to read the card from
 **
 ** @return	stream
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
istream&
Card::read(istream& istr)
{
  DEBUG_CALLING(INFO_CARD && INFO_IO,
		"Card::read(istr)");

  istr >> this->color_p >> this->value_p;

  DEBUG_RETURNING(istr,
		  INFO_CARD && INFO_IO,
		  "Card::read(istr)");
} // istrean& Card::read(istream& istr)

/**********************************************************************
 *
 ** Card::operator bool() const
 *
 ** Parameters:  None
 *
 ** Result: if the card is a real card
 *
 ** Version: Alpha
 *
 ** Description: 
 **   
 *
 **********************************************************************/

Card::operator bool() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE, "Card::operator bool()");
  DEBUG_RETURNING( (color() != NOCARDCOLOR)
		   && (value() != NOCARDVALUE) ,
		   INFO_CARD && INFO_VALUE, "Card::operator bool()");
}


/**********************************************************************
 *
 ** Card::Color Card::color()
 *
 ** Parameters: None
 *
 ** Result: color of Card
 *
 ** Version: Alpha
 *
 ** Description: 
 **   
 *
 **********************************************************************/
Card::Color
Card::color() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE, "Card::color()");
  DEBUG_RETURNING(color_p,INFO_CARD && INFO_VALUE, "Card::color()");
}


/**********************************************************************
 *
 ** Card::TColor Card::tcolor()
 *
 ** Parameters: None
 *
 ** Result: color or TRUMP of Card
 *
 ** Version: Alpha
 *
 ** Description: 
 **   
 *
 **********************************************************************/
Card::TColor
Card::tcolor() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE, "Card::tcolor()");
  DEBUG_RETURNING((istrump() ? TRUMP : color()),
		  INFO_CARD && INFO_VALUE,
		  "Card::tcolor()");
}


/**********************************************************************
 *
 ** Card::Value Card::value()
 *
 ** Parameters: None
 *
 ** Result: value of Card
 *
 ** Version: Alpha
 *
 ** Description: 
 **   
 *
 **********************************************************************/
Card::Value
Card::value() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE, "Card::value() ");
  DEBUG_RETURNING(value_p,INFO_CARD && INFO_VALUE, "Card::value() ");
}


/**********************************************************************
 *
 ** unsigned Card::points() const
 *
 ** Parameters:	-
 *
 ** Result:	points of card
 *
 ** Version:	0.4.2
 *
 ** Description: -> result
 **   
 *
 **********************************************************************/
unsigned
Card::points() const
{
  DEBUG_CALLING(INFO_CARD && INFO_VALUE,
		"Card::points()");

  // based on structure of enum type card values 
  // here can value be direct returned
  DEBUG_RETURNING(value(),
		  INFO_CARD && INFO_VALUE,
		  "Card::points()");
} // unsigned Card::points() const

/**********************************************************************
 *
 ** string name(Card const& card)
 *
 ** Parameters:  card - the card
 *
 ** Result:  name of the card
 *
 ** Version: 0.4.1
 *
 ** Description: -> result
 *
 **********************************************************************/
string
name(Card const& card)
{
  DEBUG_CALLING(INFO_CARD && INFO_NAME,
		"string name(Card const& card)");

  DEBUG_RETURNING(name(card.color()) + " " + name(card.value()),
		  INFO_CARD && INFO_NAME,
		  "string name(Card const& card)");
} // string name(Card const& card)

/**
 **
 ** writes the card in the output stream
 **
 ** @param	ostr	output stream
 ** @param	card	card
 **
 ** @return	output stream
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
ostream&
operator<<(ostream& ostr, Card const& card)
{
  DEBUG_CALLING(INFO_CARD && INFO_IO,
		"ostream& operator<<(ostr, card)");

  ostr << name(card);

  DEBUG_RETURNING(ostr,
		  INFO_CARD && INFO_IO,
		  "ostream& operator<<(ostr, card)");
} // ostream& operator<<(ostream& ostr, Card const& card);

/**
 **
 ** read the card out of the stream
 **
 ** @param	istr	input stream
 ** @param	card	card
 **
 ** @return	output stream
 **
 ** @version	0.5.4
 **
 ** @author	Diether Knof
 **
 **/
istream&
operator>>(istream& istr, Card& card)
{
  DEBUG_CALLING(INFO_CARD && INFO_BASISTYPES && INFO_IO,
		"ostream& operator<<(ostr, card)");

  card.read(istr);

  DEBUG_RETURNING(istr,
		  INFO_CARD && INFO_BASISTYPES && INFO_IO,
		  "ostream& operator<<(ostr, card)");
} // istream& operator>>(istream& istr, Card& card);
