/**********************************************************************
 *
 *   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 "icongroups.h"
#include "gtk_gui.h"
#include "card.h"
#include "icon.h"
#include "table.h"

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

namespace GTK_DOKO {

  /**
   *
   * IconGroup::IconGroup(IconGroups* icongroups,
   *			Player const& player)
   *
   * @param	icongroups  	the icongroups, this icongroup belongs to
   * 		player  	the player, this icongroup belongs to
   *
   * @return	-
   * 
   * @version	0.4.4
   *
   * Description:	constructs the icongroup
   *
   * @author	Diether Knof
   *
   */
  IconGroup::IconGroup(IconGroups* icongroups,
		       Player const& player) :
    HTINBase(icongroups, player)
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_INIT,
		    "IconGroup::IconGroup(icongroups, player)");

      DEBUG_RETURNING(VOID,
		      INFO_GTK_ICONGROUP && INFO_GTK_INIT,
		      "IconGroup::IconGroup(icongroups, player)");
    } // IconGroup::IconGroup(IconGroups* icongroups, Player const& player) :

  /**
   *
   * IconGroups& IconGroup::icongroups()
   *
   * @param	-
   *
   * @return	the icongroups, this icongroup belongs to
   * 
   * @version	0.4.4
   *
   * Description:	Result
   *
   * @author	Diether Knof
   *
   */
  IconGroups&
    IconGroup::icongroups() 
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		    "IconGroup::icongroups()");

      DEBUG_RETURNING(static_cast<IconGroups&>(this->group()),
		      INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		      "IconGroup::icongroups()");
    } // IconGroups& IconGroup::icongroups()

  /**
   *
   * -> result
   *
   * @param	-
   *
   * @return	Starting x position of the icongroup (border to the hand)
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  int
    IconGroup::border_x()
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		    "IconGroup::border_x()");

      int value = 0; // return value

      switch(this->player().no()) {
      case 0:
      case 2:
	value = hand().start_x();
	break;
      case 1:
	value = hand().start_x() + gui().cards().width(this->player())
	  + HAND_MARGIN_LEFT;
	break;
      case 3:
	value = hand().start_x()
	  - HAND_MARGIN_RIGHT;
	break;
      default:
	DEBUG_ASSERTION(false,
			"Icongroup::border_x():\n"
			"  `this->player().no()` not valid (not 0, 1, 2, 3)");
      } // switch(this->player().no())

      DEBUG_RETURNING(value,
		      INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		      "IconGroup::border_x()");
    } // IconGroup::border_x()

  /**
   *
   * -> result
   *
   * @param	-
   *
   * @return	Starting y position of the icongroup (border to the hand)
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  int
    IconGroup::border_y()
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		    "IconGroup::border_y()");

      int value = 0; // return value

      switch(this->player().no()) {
      case 0:
	value = hand().start_y()
	  - HAND_MARGIN_BOTTOM;
	break;
      case 2:
	value = hand().start_y() + gui().cards().height(this->player())
	  + HAND_MARGIN_TOP;
	break;
      case 1:
      case 3:
	value = hand().start_y();
	break;
      default:
	DEBUG_ASSERTION(false,
			"Icongroup::border_y():\n"
			"  `this->player().no()` not valid (not 0, 1, 2, 3)");
      } // switch(this->player().no())

      DEBUG_RETURNING(value,
		      INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		      "IconGroup::border_y()");
    } // IconGroup::border_y()

  /**
   *
   * -> result
   *
   * @param	pixmap	pixmap, that is to be drawn
   *
   * @return	Starting x position of the team icon
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  int
    IconGroup::team_start_x(Pixmap const& pixmap)
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		    "IconGroup::team_start_x()");

      int value = 0; // return value

      switch(this->player().no()) {
      case 0:
      case 2:
	value = border_x() + int(0.25 * width());
	break;
      case 1:
	value = border_x();
	break;
      case 3:
	value = border_x() - pixmap.width();
	break;
      default:
	DEBUG_ASSERTION(false,
			"Icongroup::start_x():\n"
			"  `this->player().no()` not valid (not 0, 1, 2, 3)");
      } // switch(this->player().no())

      DEBUG_RETURNING(value,
		      INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		      "IconGroup::team_start_x()");
    } // IconGroup::team_start_x()

  /**
   *
   * -> result
   *
   * @param	pixmap	pixmap, that is to be drawn
   *
   * @return	Starting y position of the team icon
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  int
    IconGroup::team_start_y(Pixmap const& pixmap)
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		    "IconGroup::team_start_y()");

      int value = 0; // return value

      switch(this->player().no()) {
      case 0:
	value = border_y() - pixmap.height();
	break;
      case 2:
	value = border_y();
	break;
      case 1:
      case 3:
	value = border_y();
	break;
      default:
	DEBUG_ASSERTION(false,
			"Icongroup::start_x():\n"
			"  `this->player().no()` not valid (not 0, 1, 2, 3)");
      } // switch(this->player().no())

      DEBUG_RETURNING(value,
		      INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		      "IconGroup::team_start_y()");
    } // IconGroup::team_start_y()

  /**
   *
   * -> result
   *
   * @param	pixmap	pixmap, that is to be drawn
   *
   * @return	Starting x position of the announcement icon
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  int
    IconGroup::announcement_start_x(Pixmap const& pixmap)
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		    "IconGroup::announcement_start_x()");

      int value = 0; // return value

      switch(this->player().no()) {
      case 0:
      case 2:
	value = (this->border_x()
		 + unsigned(this->width() * 2.5 / 4 )
		 - (pixmap.width() / 2));
	break;
      case 1:
	value = this->border_x();
	break;
      case 3:
	value = this->border_x() - pixmap.width();
	break;
      default:
	DEBUG_ASSERTION(false,
			"Icongroup::start_x():\n"
			"  `this->player().no()` not valid (not 0, 1, 2, 3)");
      } // switch(this->player().no())

      DEBUG_RETURNING(value,
		      INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		      "IconGroup::announcement_start_x()");
    } // IconGroup::announcement_start_x()

  /**
   *
   * -> result
   *
   * @param	pixmap	pixmap, that is to be drawn
   *
   * @return	Starting y position of the announcement icon
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  int
    IconGroup::announcement_start_y(Pixmap const& pixmap)
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		    "IconGroup::announcement_start_y()");

      int value = 0; // return value

      switch(this->player().no()) {
      case 0:
	value = this->border_y() - pixmap.height();
	break;
      case 2:
	value = this->border_y();
	break;
      case 1:
      case 3:
	value = this->border_y() + (this->height() / 2) - (pixmap.height() / 2);
	break;
      default:
	DEBUG_ASSERTION(false,
			"Icongroup::start_x():\n"
			"  `this->player().no()` not valid (not 0, 1, 2, 3)");
      } // switch(this->player().no())

      DEBUG_RETURNING(value,
		      INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		      "IconGroup::announcement_start_y()");
    } // IconGroup::announcement_start_y()

  /**
   *
   * -> result
   *
   * @param	pixmap	pixmap, that is to be drawn
   *
   * @return	Starting x position of the swines icon
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  int
    IconGroup::swines_start_x(Pixmap const& pixmap)
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		    "IconGroup::swines_start_x()");

      int value = 0; // return value

      switch(this->player().no()) {
      case 0:
      case 2:
	value = border_x() + width() - pixmap.width();
	break;
      case 1:
	value = border_x();
	break;
      case 3:
	value = border_x() - pixmap.width();
	break;
      default:
	DEBUG_ASSERTION(false,
			"Icongroup::start_x():\n"
			"  `this->player().no()` not valid (not 0, 1, 2, 3)");
      } // switch(this->player().no())

      DEBUG_RETURNING(value,
		      INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		      "IconGroup::swines_start_x()");
    } // IconGroup::swines_start_x()

  /**
   *
   * -> result
   *
   * @param	pixmap	pixmap, that is to be drawn
   *
   * @return	Starting y position of the swines icon
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  int
    IconGroup::swines_start_y(Pixmap const& pixmap)
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		    "IconGroup::swines_start_y()");

      int value = 0; // return value

      switch(this->player().no()) {
      case 0:
	value = border_y() - pixmap.height();
	break;
      case 2:
	value = border_y();
	break;
      case 1:
      case 3:
	value = border_y() + height() - pixmap.height();
	break;
      default:
	DEBUG_ASSERTION(false,
			"Icongroup::start_x():\n"
			"  `this->player().no()` not valid (not 0, 1, 2, 3)");
      } // switch(this->player().no())

      DEBUG_RETURNING(value,
		      INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		      "IconGroup::swines_start_y()");
    } // IconGroup::swines_start_y()


  /**
   *
   * -> result
   *
   * @param	-
   *
   * @return	width of the icongroup
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  unsigned
    IconGroup::width()
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		    "IconGroup::width()");

      unsigned value = 0; // return value

      switch(this->player().no()) {
      case 0:
      case 2:
	value = hand().width();
	break;
      case 1:
      case 3:
#ifdef OUTDATED
	value = (setting(Setting::ROTATE_ICONS)
		 ? this->gui().icons().width_max(this->player())
		 : this->gui().icons().width_max());
#else
	value = this->gui().icons().width_max(this->player());
#endif
	break;
      default:
	DEBUG_ASSERTION(false,
			"IconGroup::width():\n"
			"  `this->player().no()` not valid (not 0, 1, 2, 3)");
      } // switch(this->player().no())

      DEBUG_RETURNING(value,
		      INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		      "IconGroup::width()");
    } // unsigned IconGroup::width()

  /**
   *
   * -> result
   *
   * @param	-
   *
   * @return	height of the icongroup
   * 
   * @version	0.4.4
   *
   * @author	Diether Knof
   *
   */
  unsigned
    IconGroup::height()
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		    "IconGroup::height()");

      unsigned value = 0; // return value

      switch(this->player().no()) {
      case 0:
      case 2:
#ifdef OUTDATED
	value = (setting(Setting::ROTATE_ICONS)
		 ? gui().icons().height_max(this->player())
		 : gui().icons().height_max());
#else
	value = this->gui().icons().height_max(this->player());
#endif
	break;
      case 1:
      case 3:
	value = hand().height();
	break;
      default:
	DEBUG_ASSERTION(false,
			"IconGroup::height():\n"
			"  `this->player().no()` not valid (not 0, 1, 2, 3)");
      } // switch(this->player().no())

      DEBUG_RETURNING(value,
		      INFO_GTK_ICONGROUP && INFO_GTK_VALUE,
		      "IconGroup::height()");
    } // unsigned IconGroup::height()

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

      this->team_draw(update);
      this->announcement_draw(update);
      this->swines_draw(update);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_ICONGROUP && INFO_GTK_DRAW,
		      "IconGroup::draw(update)");
    } // int IconGroup::draw(update)


  /**
   **
   ** draws the icon for the team (or gametype for the soloplayer)
   **
   ** @param	update	whether the playfield should be updated
   **			(default: true)
   **
   ** @return	-
   ** 
   ** @version	0.6.1
   **
   ** @author	Diether Knof
   **
   **/
  void
    IconGroup::team_draw(bool const update)
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_DRAW,
		    "IconGroup::team_draw()");

      if( (::game_status & GAMESTATUS::GAME)
	  && (::game_status > GAMESTATUS::GAME_RESERVATION)) {
	// draw the icon for the team

	Game const& game = this->player().game();

	// take the team of the game
	Team team = game.teaminfo_for_humans(this->player());

	Pixmap pixmap; // the pixmap to be drawn
	if (game.is_finished()
	    || (game.rule()(Rule::SHOW_SOLOPLAYER_IN_GAME)
		&& ::setting(Setting::SHOW_SOLOPLAYER_IN_GAME))) {
	  if (GAMETYPE::is_solo(game.type())) {
	    if (this->player() == game.soloplayer())
#ifdef OUTEDATED
	      pixmap = (setting(Setting::ROTATE_ICONS)
			? this->gui().icons().icon(game.type(),
						   this->player())
			: this->gui().icons().icon(game.type()));
#else
	    pixmap = this->gui().icons().icon(game.type(),
					      this->player());
#endif
	  } else if (game.type() == GAMETYPE::MARRIAGE) {
	    if (this->player() == game.soloplayer())
#ifdef OUTEDATED
	      pixmap = (setting(Setting::ROTATE_ICONS)
			? this->gui().icons().icon(game.marriage_selector(),
						   this->player())
			: this->gui().icons().icon(game.marriage_selector()));
#else
	    pixmap = this->gui().icons().icon(game.marriage_selector(),
					      this->player());
#endif
	    else if (game.marriage_selector()
		     == MARRIAGE_SELECTOR::TEAM_SET)
#ifdef OUTEDATED
	      pixmap = (setting(Setting::ROTATE_ICONS)
			? this->gui().icons().icon(team,
						   this->player())
			: this->gui().icons().icon(team));
#else
	    pixmap = this->gui().icons().icon(team,
					      this->player());
#endif
	  } else if (this->player().game().type() == GAMETYPE::POVERTY) {
	    if ((this->player() == game.soloplayer())) {
#ifdef OUTEDATED
	      pixmap = (setting(Setting::ROTATE_ICONS)
			? this->gui().icons().icon(game.type(),
						   this->player())
			: this->gui().icons().icon(game.type()));
#else
	      pixmap = this->gui().icons().icon(game.type(),
						this->player());
#endif
	    } else if (this->player().team() == TEAM::RE) {
#ifdef OUTEDATED
	      pixmap = (setting(Setting::ROTATE_ICONS)
			? this->gui().icons().icon(team,
						   this->player())
			: this->gui().icons().icon(team));
#else
	      pixmap = this->gui().icons().icon(team,
						this->player());
#endif
	    } // if !(this->player().team() == TEAM::RE)
	  } // if (gametype == ...)
	} // if (soloplayer is shown)
	if (!pixmap
	    && (game.is_finished()
		|| (game.rule()(Rule::SHOW_KNOWN_TEAMS_IN_GAME)
		    && ::setting(Setting::SHOW_KNOWN_TEAMS_IN_GAME)))
	   ) {
#ifdef OUTDATED
	  pixmap = (setting(Setting::ROTATE_ICONS)
		    ? this->gui().icons().icon(team,
					       this->player())
		    : this->gui().icons().icon(team));
#else
	  pixmap = this->gui().icons().icon(team,
					    this->player());
#endif
	}

	if (pixmap) {
	  pixmap.draw(this->icongroups().table().pixmap(),
		      this->team_start_x(pixmap), this->team_start_y(pixmap));

	  this->announcement_draw(update);

	  // update the DrawingArea
	  if (update)
	    icongroups().table().update(this->team_start_x(pixmap),
					this->team_start_y(pixmap),
					this->width() + 1,
					this->height() + 1);
	} // if (pixmap)

      } // if (game_status == ...)

      DEBUG_RETURNING(VOID,
		      INFO_GTK_ICONGROUP && INFO_GTK_DRAW,
		      "IconGroup::team_draw()");
    } // void IconGroup::team_draw(bool const update)

  /**
   *
   * Draws the icon for the announcement
   *
   * @param	update	whether the playfield should be updated
   *			(default: true)
   *
   * @return	-
   * 
   * @version	Prototype
   *
   * @author	Diether Knof
   *
   */
  void
    IconGroup::announcement_draw(bool const update)
    {
      DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_DRAW,
		    "IconGroup::announcement_draw()");

      Pixmap pixmap;

      Game const& game = this->player().game();

      // setting the pixmap, if the player has make an announcement
      if (game.announcement_of_player(this->player()).announcement
	  != ANNOUNCEMENT::NOANNOUNCEMENT) {
#ifdef OUTDATED
	pixmap = (::setting(Setting::ROTATE_ICONS)
		  ? gui().icons().icon(game.announcement_of_player(this->player()),
				       this->player())
		  : gui().icons().icon(game.announcement_of_player(this->player()))
		 );
#else
	pixmap = gui().icons().icon(game.announcement_of_player(this->player()).announcement,
				    this->player());
#endif

	pixmap.draw(icongroups().table().pixmap(),
		    announcement_start_x(pixmap), announcement_start_y(pixmap));

	// update the DrawingArea
	if (update)
	  icongroups().table().update(announcement_start_x(pixmap),
				      announcement_start_y(pixmap),
				      width() + 1,
				      height() + 1);
      } // if (game.announcement(this->playerno()) != NOANNOUNCEMENT) {

      DEBUG_RETURNING(VOID,
		      INFO_GTK_ICONGROUP && INFO_GTK_DRAW,
		      "IconGroup::announcement_draw()");
    } // int IconGroup::announcement_draw()

    /**
     *
     * draws the icon for the swines
     *
     * @param	update	whether the playfield should be updated
     *			(default: true)
     *
     * @return	-
     * 
     * @version	0.4.4
     *
     * @author	Diether Knof
     *
     */
    void
      IconGroup::swines_draw(bool const update)
      {
	DEBUG_CALLING(INFO_GTK_ICONGROUP && INFO_GTK_DRAW,
		      "IconGroup::swines_draw()");

	Pixmap pixmap;

	Game const& game = this->player().game();

	// setting the pixmap, if the player has swines/hyperswines
	if (this->player().swines_has()
	    && this->player().hyperswines_has()) {
#ifdef OUTDATED
	  pixmap = (::setting(Setting::ROTATE_ICONS)
		    ? gui().icons().swines_hyperswines(game.trumpcolor(),
						       this->player())
		    : gui().icons().swines_hyperswines(game.trumpcolor())
		   );
#else
	  pixmap = gui().icons().swines_hyperswines(game.trumpcolor(),
						    this->player());
#endif
	} else if (this->player().swines_has()) {
#ifdef OUTDATED
	  pixmap = (::setting(Setting::ROTATE_ICONS)
		    ? gui().icons().swines(game.trumpcolor(),
					   this->player())
		    : gui().icons().swines(game.trumpcolor())
		   );
#else
	  pixmap = gui().icons().swines(game.trumpcolor(),
					this->player());
#endif
	} else if (this->player().hyperswines_has()) {
#ifdef OUTDATED
	  pixmap = (::setting(Setting::ROTATE_ICONS)
		    ? gui().icons().hyperswines(game.trumpcolor(),
						this->player())
		    : gui().icons().hyperswines(game.trumpcolor())
		   );
#else
	  pixmap = gui().icons().hyperswines(game.trumpcolor(),
					     this->player());
#endif
	} // if (game.player(playerno()).swines_has())

	if (pixmap) {
	  pixmap.draw(icongroups().table().pixmap(),
		      swines_start_x(pixmap), swines_start_y(pixmap));
	  this->announcement_draw(update);

	  // update the DrawingArea
	  if (update)
	    icongroups().table().update(swines_start_x(pixmap),
					swines_start_y(pixmap),
					width() + 1,
					height() + 1);
	}

	DEBUG_RETURNING(VOID,
			INFO_GTK_ICONGROUP && INFO_GTK_DRAW,
			"IconGroup::swines_draw()");
      } // int IconGroup::swines_draw()

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