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

#ifdef USE_UI_GTK

#include "names.h"
#include "gtk_gui.h"
#include "card.h"
#include "hands.h"
#include "table.h"
#include "playfield.h"

#include "../../party/party.h"
#include "../../party/rule.h"
#include "../../game/game.h"
#include "../../player/player.h"

namespace GTK_DOKO {

  /**
   *
   * constructor
   *
   * @param	player   the player, this name belongs to
   *
   * @return	-
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  Name::Name(Names* names, Player const& player) :
    HTINBase(names, player)
    {
      DEBUG_CALLING(INFO_GTK_NAME && INFO_GTK_INIT,
		    "Name::Name(names, player)");

      DEBUG_RETURNING(VOID,
		      INFO_GTK_NAME && INFO_GTK_INIT,
		      "Name::Name(names, player)");
    } // Name::Name(Names* names, Player const& player)

  /**
   *
   * -> result
   *
   * @param	-
   *
   * @return	the names, this name belongs to
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  Names&
    Name::names()
    {
      DEBUG_CALLING(INFO_GTK_NAME && INFO_GTK_VALUE,
		    "Name::names()");

      DEBUG_RETURNING(static_cast<Names&>(this->group()),
		      INFO_GTK_NAME && INFO_GTK_VALUE,
		      "Name::names()");
    } // Names& Name::names()

  /**
   *
   * -> result
   *
   * @param	-
   *
   * @return	starting x position of the name
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  int
    Name::start_x()
    {
      DEBUG_CALLING(INFO_GTK_NAME && INFO_GTK_VALUE,
		    "Name::start_x()");

      int value = 0; // return value

      switch(this->player().no()) {
      case 0:
      case 1:
      case 2:
	value = this->hand().start_x();
	break;
      case 3: {
	// if the name is too long, right align it

	// the size of the text in the font
	int width = 0;

	// draw the name
	if (game_status != GAMESTATUS::PROGRAMSTART)
	  gdk_text_extents(names().font(),
			   this->player().name().c_str(),
			   this->player().name().length(),
			   NULL, NULL, &width, NULL, NULL);
	value = std::min(static_cast<unsigned>(this->hand().start_x()),
			 this->hand().start_x()
			 + this->hand().width()
			 - width);
	break;
      }
#if RIGHT_ALIGN
      case 2: {
	// the size of the text in the font
	int width = 0;

	// draw the name
	if (game_status != GAMESTATUS::PROGRAMSTART)
	  gdk_text_extents(names().font(),
			   this->player().name().c_str(),
			   this->player().name().length(),
			   NULL, NULL, &width, NULL, NULL);
	value = this->hand().start_x() + this->hand().width() - width;
	break;
      }
#endif
      default:
	DEBUG_ASSERTION(false,
			"Name::start_x()\n"
			"  'this->player().no()' is not 0, 1, 2 or 3");
      }

      DEBUG_RETURNING(value,
		      INFO_GTK_NAME && INFO_GTK_VALUE,
		      "Name::start_x()");
    } // Name::start_x()

  /**
   *
   * -> result
   *
   * @param	-
   *
   * @return	starting y position of the name
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  int
    Name::start_y()
    {
      DEBUG_CALLING(INFO_GTK_NAME && INFO_GTK_VALUE,
		    "Name::start_y()");

      int value = 0; // return value

      switch(this->player().no()) {
      case 0:
	value = this->hand().start_y() - HAND_MARGIN_BOTTOM;
	break;
      case 1:
	value = this->hand().start_y() - HAND_MARGIN_LEFT;
	break;
      case 2:
	value = (this->hand().start_y() + this->hand().height() + HAND_MARGIN_TOP
		 + this->names().font()->ascent);
	break;
      case 3:
	value = (this->hand().start_y() + this->hand().height() + HAND_MARGIN_RIGHT
		 + this->names().font()->ascent);
	break;
      default:
	DEBUG_ASSERTION(false,
			"Name::start_y()\n"
			"  'this->player().no()' is not 0, 1, 2 or 3");
      }

      DEBUG_RETURNING(value,
		      INFO_GTK_NAME && INFO_GTK_VALUE,
		      "Name::start_y()");
    } // Name::start_y()


  /**
   **
   ** Redraws the name of the player (he has a new one)
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @version	0.4.4
   **
   ** @author	Diether Knof
   **
   ** @todo	don't update all
   **
   */
  void
    Name::set()
    {
      DEBUG_CALLING(INFO_GTK_NAME && INFO_GTK_UPDATE,
		    "Name::set()");

      // the whole table has to be drawn
      this->names().table().draw_all();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_NAME && INFO_GTK_UPDATE,
		      "Name::set()");
    } // void Name::set()

  /**
   *
   * draws the name in the table
   *
   * @param	update	Whether the name should be updated (default: true)
   *
   * @return	-
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  void
    Name::draw(bool const update)
    {
      DEBUG_CALLING(INFO_GTK_NAME && INFO_GTK_DRAW,
		    "Name::draw(update)");

      // the size of the text in the font
      int lbearing, rbearing, width, ascent, descent;

      // draw the name
      if (game_status & GAMESTATUS::GAME) {
	gdk_text_extents(this->names().font(),
			 this->player().name().c_str(),
			 this->player().name().length(),
			 &lbearing, &rbearing, &width, &ascent, &descent);
	GdkGC* gc = NULL;

	{ // test whether this is the active player
	  bool is_active = false;
	  switch (::game_status) {
	  case GAMESTATUS::GAME_RESERVATION:
	  case GAMESTATUS::GAME_SHOW_GAMETYPE:
	  case GAMESTATUS::GAME_REDISTRIBUTE:
	  case GAMESTATUS::GAME_POVERTY_SHIFT:
	    if (is_solo(this->player().game().type())
		&& (this->player().game().rule()(Rule::LUSTSOLO_PLAYER_LEADS)))
	      is_active = (this->player()
			   == this->player().game().player_current());
	    else
	      is_active = (this->player()
			   == this->player().game().startplayer());

		break;
	  case GAMESTATUS::GAME_PLAY:
	  case GAMESTATUS::GAME_GENSCHER:
	  case GAMESTATUS::GAME_SHOW_FULL_TRICK:
	  case GAMESTATUS::GAME_SHOW_LAST_TRICK:
	    is_active = (this->player()
			 == this->player().game().player_current());
	    break;
	  case GAMESTATUS::GAME_FINISHED:
	    if (this->gui().playfield().table().last_trick().trickno()
		== UINT_MAX) {
	      is_active = (this->player().team()
			   == this->player().game().winnerteam());
	    } else { // if (show a specific trick)
	      is_active = (this->player()
			   == this->player().game().trick(this->gui().playfield().table().last_trick().trickno()).winnerplayer());
	    } // if (show a specific trick)
	    break;

	  default:
	    break;
	  } // switch (::game_status)
	  if (is_active)
	    gc = this->names().gc_active();
	  else
	    gc = this->names().gc();
	} // test whether it is the active player
	if (update) {
	  this->names().table().background_draw(this->start_x() - lbearing,
						this->start_y() - ascent,
						width + lbearing + rbearing + 1,
						ascent + descent);
#ifdef WORKAROUND
	  // the width of player 2 is calculated too width
	  this->icongroup().draw(false);
#endif
	} // if (update)

	gdk_draw_text(this->names().table().pixmap(),
		      this->names().font(), gc,
		      this->start_x(),
		      this->start_y(),
		      this->player().name().c_str(),
		      this->player().name().length());
      }

      // update the DrawingArea
      if (update)
	this->names().table().update(this->start_x() - lbearing,
				     this->start_y() - ascent,
				     width + lbearing + rbearing + 1,
				     ascent + descent);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_NAME && INFO_GTK_DRAW,
		      "Name::draw(update)");
    } // int Name::draw(update)

} // namespace GTK_DOKO
#endif // #ifdef USE_UI_GTK
