/**********************************************************************
 *
 *  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 "player.h"
#include "aiconfig.h"
#include "gtk_gui.h"

#include "../../party/party.h"
#include "../../player/namegen.h"
#include "../../misc/language.h"

namespace GTK_DOKO {

  /**
   **
   ** Constructor
   **
   **
   ** @param	players_a	the players
   ** @param	playerno_a	playernumber
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  PartySettings::Players::Player::Player(PartySettings::Players* const players,
					 unsigned const playerno) :
    players_(players),
  playerno_(playerno),
  player_bak(NULL),
  alignment(gtk_alignment_new(0.5, 0.5, 0, 0)),
  name_container(gtk_hbox_new(FALSE, 0)),
  name_label(gtk_label_new("")),
  name_entry(gtk_entry_new()),
  name_button(gtk_button_new_with_label("")),
  type_container(gtk_hbox_new(FALSE, 0)),
  type_label(gtk_label_new("")),
  type_human(gtk_radio_button_new_with_label(NULL, "")),
  type_ai(gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(type_human), "")),
  type_ai_dummy(gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(type_human), "")),
  config_button(gtk_button_new_with_label(""))
  {
    DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_INIT,
		  "PartySettings::Players::Player::Player()");

    GtkWidget* container = gtk_vbutton_box_new();

    gtk_entry_set_editable(GTK_ENTRY(this->name_entry), TRUE);

    // pack the widgets in the container
    gtk_container_add(GTK_CONTAINER(this->alignment), container);
    // the name
    gtk_container_add(GTK_CONTAINER(container), this->name_container);
    gtk_container_add(GTK_CONTAINER(name_container), this->name_label);
    gtk_container_add(GTK_CONTAINER(name_container), this->name_entry);
    gtk_container_add(GTK_CONTAINER(name_container), this->name_button);
    // the type
    gtk_container_add(GTK_CONTAINER(container), this->type_container);
    gtk_container_add(GTK_CONTAINER(type_container), this->type_label);
    gtk_container_add(GTK_CONTAINER(type_container), this->type_human);
    gtk_container_add(GTK_CONTAINER(type_container), this->type_ai);
#ifndef RELEASE
    gtk_container_add(GTK_CONTAINER(type_container), this->type_ai_dummy);
#endif

    { // configuration the ai
      GtkWidget* alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
      gtk_container_add(GTK_CONTAINER(alignment), this->config_button);
      gtk_container_add(GTK_CONTAINER(container), alignment);
    } //  // configuration the ai

    // event for generating a random name
    gtk_signal_connect(GTK_OBJECT(this->name_button), "clicked",
		       GTK_SIGNAL_FUNC(random_name_event),
		       this);

    // name change
    gtk_signal_connect(GTK_OBJECT(this->name_entry),
		       "changed",
		       GTK_SIGNAL_FUNC(PartySettings::Players::Player::name_changed_event),
		       gpointer(this));

    // change of the type
    gtk_signal_connect(GTK_OBJECT(this->type_human),
		       "clicked",
		       GTK_SIGNAL_FUNC(type_changed_event),
		       gpointer(this));
    gtk_signal_connect(GTK_OBJECT(this->type_ai),
		       "clicked",
		       GTK_SIGNAL_FUNC(type_changed_event),
		       gpointer(this));
    gtk_signal_connect(GTK_OBJECT(this->type_ai_dummy),
		       "clicked",
		       GTK_SIGNAL_FUNC(type_changed_event),
		       gpointer(this));

    // show the configuration window when the button is clicked
    gtk_signal_connect(GTK_OBJECT(this->config_button),
		       "clicked",
		       GTK_SIGNAL_FUNC(configure_event),
		       gpointer(this));
#ifdef POSTPHONED 
    // close the configuration window when the party settings window is hidden
    gtk_signal_connect(GTK_OBJECT(this->players().party_settings().window()),
		       "hide",
		       GTK_SIGNAL_FUNC(Dialog::hide_event),
		       gpointer(this->aiconfig));
#endif


    this->language_update();
    gtk_widget_show_all(this->widget());

    DEBUG_RETURNING(VOID,
		    INFO_GTK_PLAYERS && INFO_GTK_INIT,
		    "PartySettings::Players::Player::Player()");
  } // PartySettings::Players::Player::Player(players_a, playerno_a)

  /**
   **
   ** Destructor
   **
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  PartySettings::Players::Player::~Player()
  {
    DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_INIT,
		  "PartySettings::Players::Player::~Player()");

    this->backup_destroy();

    DEBUG_RETURNING(VOID,
		    INFO_GTK_PLAYERS && INFO_GTK_INIT,
		    "PartySettings::Players::Player::~Player()");
  } // PartySettings::Players::Player::~Player()

  /**
   **
   ** update the sensitivity
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::Players::Player::sensitivity_update()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_INIT,
		    "PartySettings::Players::Player::sensitivity_update()");

      if (::game_status == GAMESTATUS::PARTY_INIT)
	gtk_widget_set_sensitive(type_container, TRUE);
#ifdef POSTPHONED
      // This is for changing the type of the player during the game.
      // But there are problems because the player-pointer in 'Game' have
      // also to be changed.
      // Perhaps use pointer to pointer in 'Game'.
      // The same is then for 'trick' (startplayer, winnerplayer).
      else if ((::game_status & GAMESTATUS::GAME)
	       && ::party.game().trick_current().isfull())
	gtk_widget_set_sensitive(type_container, TRUE);
#endif // #ifdef POSTPHONED
      else
	gtk_widget_set_sensitive(type_container, FALSE);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_INIT,
		      "PartySettings::Players::Player::sensitivity_update()");
    } // void PartySettings::Players::Player::sensitivity_update()

  /**
   **
   ** create a backup
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::Players::Player::backup()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		    "PartySettings::Players::Player::backup()");

      this->backup_destroy();
      this->player_bak = this->player().clone();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		      "PartySettings::Players::Player::backup()");
    } // void PartySettings::Players::Player::backup()

  /**
   **
   ** destroy the backup
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::Players::Player::backup_destroy()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		    "PartySettings::Players::Player::backup_destroy()");

      delete this->player_bak;
      this->player_bak = NULL;

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		      "PartySettings::Players::Player::backup_destroy()");
    } // void PartySettings::Players::Player::backup_destroy()

  /**
   **
   ** reset the settings
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::Players::Player::reset()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		    "PartySettings::Players::Player::reset()");

      // overwrite player in party with the backup
      ::party.player_set(this->player_bak->clone(), this->playerno());

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		      "PartySettings::Players::Player::reset()");
    } // void PartySettings::Players::Player::reset()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the gui
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.2
   **
   **/
  GTK_GUI&
    PartySettings::Players::Player::gui()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		    "PartySettings::Players::Player::gui()");

      DEBUG_RETURNING(this->players().gui(),
		      INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		      "PartySettings::Players::Player::gui()");
    } // GTK_GUI& PartySettings::Players::Player::gui()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	all players
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.2
   **
   **/
  PartySettings::Players&
    PartySettings::Players::Player::players()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		    "PartySettings::Players::Player::players()");

      DEBUG_ASSERTION((this->players_ != NULL),
		      "PartySettings::Players::Player::players()\n"
		      "  `this->players_` == NULL");

      DEBUG_RETURNING(*(this->players_),
		      INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		      "PartySettings::Players::Player::players()");
    } // PartySettings::Players& PartySettings::Players::Player::players()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the playernumber of the corresponding player
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.2
   **
   **/
  unsigned
    PartySettings::Players::Player::playerno() const
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		    "PartySettings::Players::Player::playerno()");

      DEBUG_RETURNING(this->playerno_,
		      INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		      "PartySettings::Players::Player::playerno()");
    } // unsigned PartySettings::Players::Player::playerno()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the corresponding player
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.2
   **
   **/
  ::Player&
    PartySettings::Players::Player::player()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		    "PartySettings::Players::Player::player()");

      DEBUG_RETURNING(::party.player(this->playerno()),
		      INFO_GTK_PLAYERS && INFO_GTK_VALUE,
		      "PartySettings::Players::Player::player()");
    } // Player& PartySettings::Players::Player::player()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the widget
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.2
   **
   **/
  GtkWidget*
    PartySettings::Players::Player::widget()
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		    "PartySettings::Players::Player::widget()");

      DEBUG_RETURNING(this->alignment,
		      INFO_GTK_SETTINGS && INFO_GTK_VALUE,
		      "PartySettings::Players::Player::widget()");
    } // GtkWidget* PartySettings::Players::Player::widget()


  /**
   **
   ** event: select a random name
   **
   ** @param	player	player of the event
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::Players::Player::random_name_event(GtkWidget*, gpointer player)
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		    "PartySettings::Players::Player::random_name_event()");

      static_cast<Player*>(player)->random_name();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		      "PartySettings::Players::Player::random_name_event()");
    } // static void PartySettings::Players::Player::random_name_event(GtkWidget*, gpointer player)

  /**
   **
   ** event: the name has changed
   **
   ** @param	player	player of the event
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::Players::Player::name_changed_event(GtkWidget*, gpointer player)
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		    "PartySettings::Players::Player::name_changed_event()");

      static_cast<Player*>(player)->name_changed();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		      "PartySettings::Players::Player::name_changed_event()");
    } // static void PartySettings::Players::Player::name_changed_event(GtkWidget*, gpointer player)

  /**
   **
   ** event: change of the type
   **
   ** @param	player	player of the event
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::Players::Player::type_changed_event(GtkWidget* widget,
						       gpointer player)
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		    "PartySettings::Players::Player::type_changed_event()");

      if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))
	  == TRUE)
	static_cast<Player*>(player)->type_changed();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		      "PartySettings::Players::Player::type_changed_event()");
    } // static void PartySettings::Players::Player::type_changed_event(GtkWidget*, gpointer player)

  /**
   **
   ** event: configure the player (aiconfig)
   **
   ** @param	player	player of the event
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::Players::Player::configure_event(GtkWidget*, gpointer player)
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		    "PartySettings::Players::Player::configure_event()");

      static_cast<Player*>(player)->configure();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		      "PartySettings::Players::Player::configure_event()");
    } // static void PartySettings::Players::Player::configure_event(GtkWidget*, gpointer player)

  /**
   **
   ** event: random name for the player
   **
   ** @param	player	player of the event
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::Players::Player::random_name()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		    "PartySettings::Players::Player::random_name()");

      ::party.playername_set(this->playerno(),
			     ::generate_name(4 + RAND(3)));

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		      "PartySettings::Players::Player::random_name()");
    } // static void PartySettings::Players::Player::random_name()

  /**
   **
   ** The name of the player has changed.
   ** 
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::Players::Player::name_changed()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		    "PartySettings::Players::Player::name_changed()");

      // ToDo: block 'Entry::change_signal()'
      // Now, the entry is first cleared (that leads to an inserting of the 
      // default name), afterwards the new name is inserted.
      // So in the end the name is the old name followed by the default name.

      ::party.playername_set(this->player().no(),
			     gtk_entry_get_text(GTK_ENTRY(this->name_entry)));

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		      "PartySettings::Players::Player::name_changed()");
    } // void PartySettings::Players::Player::name_changed()

  /**
   **
   ** The type of the player has changed.
   ** Perhaps the default name has to be updated
   ** 
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::Players::Player::type_changed()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		    "PartySettings::Players::Player::type_changed()");

      ::Player::Type type = ::Player::UNSET;

      if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(type_human)))
	type = ::Player::HUMAN;
      else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(type_ai)))
	type = ::Player::AI;
      else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(type_ai_dummy)))
	type = ::Player::AI_DUMMY;
      else
	DEBUG_ASSERTION(false,
			"PartySettings::Players::Player::type_changed():\n"
			"  no type button active");
      ::party.playertype_set(this->playerno(), type);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		      "PartySettings::Players::Player::type_changed()");
    } // void PartySettings::Players::Player::type_changed()

  /**
   **
   ** configure the player
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::Players::Player::configure()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		    "PartySettings::Players::Player::configure()");

      this->players().aiconfigs().show(this->playerno());

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_EVENT,
		      "PartySettings::Players::Player::configure()");
    } // static void PartySettings::Players::Player::configure()

  /**
   **
   ** update all
   ** 
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::Players::Player::update()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_UPDATE,
		    "PartySettings::Players::Player::update()");

      this->name_update();
      this->type_update();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_UPDATE,
		      "PartySettings::Players::Player::update()");
    } // void PartySettings::Players::Player::update()

  /**
   **
   ** The name of the player has changed.
   ** 
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::Players::Player::name_update()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_UPDATE,
		    "PartySettings::Players::Player::name_update()");

      if (gtk_entry_get_text(GTK_ENTRY(this->name_entry))
	  != this->player().name_value())
	gtk_entry_set_text(GTK_ENTRY(this->name_entry),
			   this->player().name_value().c_str());

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_UPDATE,
		      "PartySettings::Players::Player::name_update()");
    } // void PartySettings::Players::Player::name_update()

  /**
   **
   ** The type of the player has changed.
   ** 
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::Players::Player::type_update()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_UPDATE,
		    "PartySettings::Players::Player::type_update()");

      switch (this->player().type()) {
      case ::Player::HUMAN:
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->type_human),
				     TRUE);
	break;
      case ::Player::AI:
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->type_ai),
				     TRUE);
	break;
      case ::Player::AI_DUMMY:
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->type_ai_dummy),
				     TRUE);
	break;
      case ::Player::UNSET:
	DEBUG_ASSERTION(false,
			"PartySettings::Players::Player::type_update():\n"
			"  player type is 'UNSET'");
      } // switch (this->player().type())

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_UPDATE,
		      "PartySettings::Players::Player::type_update()");
    } // void PartySettings::Players::Player::type_update()

  /**
   **
   ** update the language
   ** 
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::Players::Player::language_update()
    {
      DEBUG_CALLING(INFO_GTK_PLAYERS && INFO_GTK_UPDATE,
		    "PartySettings::Players::Player::language_update()");

      // the buttons and labels and so on
      gtk_label_set_text(GTK_LABEL(name_label),
			 (::language("Name") + ": ").c_str());
      gtk_label_set_text(GTK_LABEL(GTK_BIN(name_button)->child),
			 ::language("random").c_str());
      gtk_label_set_text(GTK_LABEL(type_label),
			 (::language("Type") + ": ").c_str());
      gtk_label_set_text(GTK_LABEL(GTK_BIN(type_human)->child),
			 ::language(::Player::HUMAN).c_str());
      gtk_label_set_text(GTK_LABEL(GTK_BIN(type_ai)->child),
			 ::language(::Player::AI).c_str());
      gtk_label_set_text(GTK_LABEL(GTK_BIN(type_ai_dummy)->child),
			 ::language(::Player::AI_DUMMY).c_str());

      gtk_label_set_text(GTK_LABEL(GTK_BIN(config_button)->child),
			 (" " + ::language("configure") + " ").c_str());

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYERS && INFO_GTK_UPDATE,
		      "PartySettings::Players::Player::language_update()");
    } // void PartySettings::Players::Player::language_update()

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