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

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

namespace GTK_DOKO {
#include <gtk/gtklabel.h>

  /**
   **
   ** constructor
   **
   ** @param	party_settings	party settings
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  PartySettings::General::General(PartySettings* const party_settings) :
    party_settings_(party_settings),
  startseed_bak(UINT_MAX),
  startplayer_bak(UINT_MAX),
  alignment(gtk_alignment_new(0.5, 0.5, 0, 0)),
  seed_frame(gtk_frame_new("game seed")),
  seed_value(gtk_spin_button_new(GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, PSEUDO_RAND_MAX, 1, 0, 0)), 1, 0)),
  seed_random(gtk_check_button_new_with_label("random")),
  startplayer_frame(gtk_frame_new("startplayer")),
  startplayer(),
  startplayer_random(gtk_radio_button_new_with_label(NULL, "random"))
  {
    DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_INIT,
		  "PartySettings::General::General()");

    gtk_container_set_border_width(GTK_CONTAINER(this->alignment), 20);

    // ***ToDo DK
    // the entry of the spin button should be great enough to contain six digits
    gtk_widget_set_usize(GTK_WIDGET(GTK_ENTRY(this->seed_value)),
			 100, 0);

    // the startplayer
    gtk_object_set_data(GTK_OBJECT(this->startplayer_random),
			"startplayerno",
			new unsigned(UINT_MAX));
    for (unsigned p = 0; p < ::party.playerno(); p++) {
      this->startplayer.push_back(gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(this->startplayer_random),
									      "player name"));
      gtk_object_set_data(GTK_OBJECT(this->startplayer.back()),
			  "startplayerno",
			  new unsigned(p));
    } // for (p < ::party.playerno())


    { // pack the widgets in the container
      GtkWidget* container = gtk_vbox_new(FALSE, 20);

      { // the seed
	GtkWidget* seed_alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
	GtkWidget* seed_container = gtk_vbutton_box_new();

	gtk_container_add(GTK_CONTAINER(seed_container),
			  this->seed_value);
	gtk_container_add(GTK_CONTAINER(seed_container),
			  this->seed_random);

	gtk_container_set_border_width(GTK_CONTAINER(seed_container), 20);

	gtk_container_add(GTK_CONTAINER(this->seed_frame), seed_container);
	gtk_container_add(GTK_CONTAINER(seed_alignment), this->seed_frame);
	gtk_container_add(GTK_CONTAINER(container), seed_alignment);
      } // the seed

      { // the startplayer
	GtkWidget* startplayer_table = gtk_table_new(3, 3, TRUE);

	gtk_table_set_row_spacings(GTK_TABLE(startplayer_table), 5);
	gtk_table_set_col_spacings(GTK_TABLE(startplayer_table), 5);

	gtk_table_attach_defaults(GTK_TABLE(startplayer_table),
				  this->startplayer[0],
				  1, 2, 2, 3);
	gtk_table_attach_defaults(GTK_TABLE(startplayer_table),
				  this->startplayer[1],
				  0, 1, 1, 2);
	gtk_table_attach_defaults(GTK_TABLE(startplayer_table),
				  this->startplayer[2],
				  1, 2, 0, 1);
	gtk_table_attach_defaults(GTK_TABLE(startplayer_table),
				  this->startplayer[3],
				  2, 3, 1, 2);
	gtk_table_attach_defaults(GTK_TABLE(startplayer_table),
				  this->startplayer_random,
				  1, 2, 1, 2);

	gtk_container_set_border_width(GTK_CONTAINER(startplayer_table), 20);

	gtk_container_add(GTK_CONTAINER(this->startplayer_frame),
			  startplayer_table);
	gtk_container_add(GTK_CONTAINER(container), this->startplayer_frame);
      } // the startplayer

      gtk_container_add(GTK_CONTAINER(this->alignment), container);
    } // pack the widgets in the container

    // the signals
    gtk_signal_connect(GTK_OBJECT(this->seed_value), "changed",
		       GTK_SIGNAL_FUNC(PartySettings::General::seed_event),
		       gpointer(this));
    // the signals
    gtk_signal_connect(GTK_OBJECT(this->seed_random), "clicked",
		       GTK_SIGNAL_FUNC(PartySettings::General::seed_random_event),
		       gpointer(this));
    for (unsigned p = 0; p < ::party.playerno(); p++)
      gtk_signal_connect(GTK_OBJECT(this->startplayer[p]), "clicked",
			 GTK_SIGNAL_FUNC(PartySettings::General::startplayer_event),
			 gpointer(this));
    gtk_signal_connect(GTK_OBJECT(this->startplayer_random), "clicked",
		       GTK_SIGNAL_FUNC(PartySettings::General::startplayer_event),
		       gpointer(this));


    this->update();
    this->language_update();

    gtk_widget_show_all(this->widget());


    DEBUG_RETURNING(VOID,
		    INFO_GTK_PARTY_SETTINGS && INFO_GTK_INIT,
		    "PartySettings::General::PartySettings()");
  } // PartySettings::General::General(PartySettings* party_settings_a)

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

    gtk_widget_destroy(this->alignment);

    DEBUG_RETURNING(VOID,
		    INFO_GTK_PARTY_SETTINGS && INFO_GTK_INIT,
		    "PartySettings::General::~General()");
  } // void PartySettings::General::~General()

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

      gtk_widget_set_sensitive(this->alignment,
			       (::game_status == GAMESTATUS::PARTY_INIT));

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_INIT,
		      "PartySettings::General::sensitivity_update()");
    } // void PartySettings::General::sensitivity_update()

  /**
   **
   ** create a backup
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::General::backup()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_INIT,
		    "PartySettings::General::backup()");

      this->startseed_bak = ::party.seed_first();
      this->startplayer_bak = ::party.startplayer_first();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_INIT,
		      "PartySettings::General::backup()");
    } // void PartySettings::General::backup()

  /**
   **
   ** destroy the backup
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::General::backup_destroy()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_INIT,
		    "PartySettings::General::backup_destroy()");

      this->startseed_bak = UINT_MAX;
      this->startplayer_bak = UINT_MAX;

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_INIT,
		      "PartySettings::General::backup_destroy()");
    } // void PartySettings::General::backup_destroy()

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

      // set the seed (UINT_MAX means random seed)
      bool const random_seed = (this->startseed_bak == UINT_MAX);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(this->seed_value),
				((this->startseed_bak == UINT_MAX)
				 ? float(0)
				 : float(this->startseed_bak)));
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->seed_random),
				   random_seed);

      // set the startplayer
      if (this->startplayer_bak == UINT_MAX)
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->startplayer_random),
				     TRUE);
      else
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->startplayer[this->startplayer_bak]),
				     TRUE);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		      "PartySettings::General::reset()");
    } // void PartySettings::General::reset()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the gui
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  GTK_GUI&
    PartySettings::General::gui()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_VALUE,
		    "PartySettings::General::gui()");

      DEBUG_RETURNING(this->party_settings().gui(),
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_VALUE,
		      "PartySettings::General::gui()");
    } // GTK_GUI& PartySettings::General::gui()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the party settings
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  PartySettings&
    PartySettings::General::party_settings()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_VALUE,
		    "PartySettings::General::party_settings()");

      DEBUG_ASSERTION((this->party_settings_ != NULL),
		      "PartySettings::General::party_settings()\n"
		      "  `party_settings_` == NULL");

      DEBUG_RETURNING(*(this->party_settings_),
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_VALUE,
		      "PartySettings::General::party_settings()");
    } // PartySettings& PartySettings::General::party_settings()

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

      DEBUG_ASSERTION((this->alignment != NULL),
		      "PartySettings::General::widget()\n"
		      "  `alignment` == NULL");

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

  /**
   **
   ** event, that the seed has changed
   **
   ** @param	seed		widget with the seed
   ** @param	general		the PartySettings::General
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::General::seed_event(GtkWidget* seed, gpointer general)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		    "PartySettings::General::seed_event()");

      ::party.seed_first_set(static_cast<unsigned>(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(seed))));

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		      "PartySettings::General::seed_event()");
    } // static void PartySettings::General::seed_event(GtkWidget* seed, gpointer general)

  /**
   **
   ** event, that the random seed button has been pressed
   **
   ** @param	seed_random	button that has been pressed
   ** @param	general		the PartySettings::General
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::General::seed_random_event(GtkWidget* seed_random,
					      gpointer general)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		    "PartySettings::General::seed_random_event()");

      static_cast<PartySettings::General*>(general)->seed_random_set(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(seed_random)));

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		      "PartySettings::General::seed_random_event()");
    } // static void PartySettings::General::seed_random_event(GtkWidget* seed_random, gpointer general)

  /**
   **
   ** event, that the startplayer has changed
   **
   ** @param	startplayer	startplayer button that has been pressed
   ** @param	general		the PartySettings::General
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.6.2
   **
   **/
  void
    PartySettings::General::startplayer_event(GtkWidget* startplayer,
					      gpointer general)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		    "PartySettings::General::startplayer_event()");

      if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(startplayer))
	  == TRUE) {
      unsigned const p = *(static_cast<unsigned*>(gtk_object_get_data(GTK_OBJECT(startplayer), "startplayerno")));

      if (p == UINT_MAX)
	::party.startplayer_first_set_random();
      else
	::party.startplayer_first_set(p);
      } // if (gtk_toggle_button_get_active(startplayer) == TRUE)


      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		      "PartySettings::General::startplayer_event()");
    } // static void PartySettings::General::startplayer_event(GtkWidget* startplayer, gpointer general)

  /**
   **
   ** the random seed button has been set/unset
   **
   ** @param	random	whether the seed should be random
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::General::seed_random_set(bool const random)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		    "PartySettings::General::seed_random_set("
		    << "random = " << random
		    << ")");

      ::party.seed_first_set(random
			     ? UINT_MAX
			     : static_cast<unsigned>(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(this->seed_value))));


      gtk_widget_set_sensitive(this->seed_value, !random);


      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		      "PartySettings::General::seed_random_set(random)");
    } // void PartySettings::General::seed_random_set(bool const random)

  /**
   **
   ** update the widgets
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   **/
  void
    PartySettings::General::update()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		    "PartySettings::General::update()");

      // set the seed (UINT_MAX means random seed)
      bool const random_seed = (::party.seed_first() == UINT_MAX);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(this->seed_value),
				(random_seed
				 ? float(0)
				 : float(::party.seed_first())));
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->seed_random),
				   !random_seed);
      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->seed_random),
				   random_seed);

      // set the startplayer
      if (::party.startplayer_first() == UINT_MAX)
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->startplayer_random),
				     TRUE);
      else
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(this->startplayer[::party.startplayer_first()]),
				     TRUE);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		      "PartySettings::General::update()");
    } // void PartySettings::General::apply()

  /**
   **
   ** updates the language of the elements
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.3
   **
   ** @todo	write the players name, not the number of the player
   **
   **/
  void
    PartySettings::General::language_update()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_UPDATE,
		    "PartySettings::General::language_update()");

      // name of the bookmark
      gtk_frame_set_label(GTK_FRAME(this->seed_frame),
			  ::language("game seed").c_str());
      gtk_label_set_text(GTK_LABEL(GTK_BIN(this->seed_random)->child),
			 ::language("random").c_str());

      gtk_frame_set_label(GTK_FRAME(this->startplayer_frame),
			  ::language("startplayer").c_str());
      for (unsigned p = 0; p < this->startplayer.size(); p++)
	gtk_label_set_text(GTK_LABEL(GTK_BIN(this->startplayer[p])->child),
			   ::party.player(p).name().c_str());

      gtk_label_set_text(GTK_LABEL(GTK_BIN(this->startplayer_random)->child),
			 ::language("random").c_str());

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_UPDATE,
		      "PartySettings::General::language_update()");
    } // void PartySettings::General::language_update()

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