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

#include "gtk_gui.h"
#include "bug_report.h"
#include "main_window.h"

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

namespace GTK_DOKO {

  /**
   **
   ** Constructor
   **
   ** @param	playfield	pointer to the playfield
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.2
   **
   **/
  PartySettings::PartySettings(Playfield* const playfield) :
    PlayfieldDialog(playfield, "Settings of the party"), // the base class
  general(new General(this)),
  players(new Players(this)),
  rules(new Rules(this)),
  button_reset(gtk_button_new_with_label("reset")),
  button_bug_report_load(gtk_button_new_with_label("load bug report")),
  button_start_party(gtk_button_new_with_label("start party"))
  {
    DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_INIT,
		  "PartySettings::PartySettings()");

    // the buttons
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(this->window())->action_area),
		      this->button_reset);
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(this->window())->action_area),
		      this->button_bug_report_load);
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(this->window())->action_area),
		      this->button_start_party);
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(this->window())->action_area),
		      this->button_close);

    // the notebook
    this->notebook_ = gtk_notebook_new();
    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(this->window())->vbox),
		       this->notebook_, TRUE, TRUE, 10);

    this->label_general = gtk_label_new("general");
    gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook_),
			     this->general->widget(),
			     this->label_general);

    this->label_players = gtk_label_new("players");
    gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook_),
			     this->players->widget(),
			     this->label_players);

    this->label_rules = gtk_label_new("rules");
    gtk_notebook_append_page(GTK_NOTEBOOK(this->notebook_),
			     this->rules->widget(),
			     this->label_rules);

#ifdef POSTPHONED
    // *** DK
    // I don't know, why the 'players' page is on the top by default
    gtk_notebook_set_page(GTK_NOTEBOOK(this->notebook), 0);
#endif
    gtk_window_set_transient_for(GTK_WINDOW(this->window()),
				 GTK_WINDOW(this->gui().main_window().window()));
    { // center the window
      int x, y, width, height, wwidth, wheight;
      gdk_window_get_geometry(this->gui().main_window().window()->window,
			      &x, &y, &width, &height, NULL);
      gdk_window_get_size(this->window()->window, &wwidth, &wheight);
      gdk_window_move(this->window()->window,
		      x + width / 2 - wwidth / 2, y + height / 2 - wheight / 2);
    } // center the window

    // Buttons
    gtk_signal_connect(GTK_OBJECT(this->button_reset), "clicked",
		       GTK_SIGNAL_FUNC(PartySettings::reset_event),
		       gpointer(this));
    gtk_signal_connect(GTK_OBJECT(this->button_bug_report_load), "clicked",
		       GTK_SIGNAL_FUNC(BugReport::open_selector_event),
		       gpointer(&(this->gui().bug_report())));
    gtk_signal_connect(GTK_OBJECT(this->button_start_party), "clicked",
		       GTK_SIGNAL_FUNC(PartySettings::hide_event),
		       gpointer(this));
    // hide the bug report if the window is closed
    gtk_signal_connect(GTK_OBJECT(this->window()),
		       "hide", GTK_SIGNAL_FUNC(GTK_GUI::window_hide),
		       gpointer(this->gui().bug_report().selector));


    // show all widgets
    gtk_widget_show_all(GTK_DIALOG(this->window())->vbox);
    gtk_widget_show_all(GTK_DIALOG(this->window())->action_area);


    this->sensitivity_update();

    this->language_update();
    DEBUG_RETURNING(VOID,
		    INFO_GTK_PARTY_SETTINGS && INFO_GTK_INIT,
		    "PartySettings::PartySettings()");
  } // PartySettings::PartySettings(Playfield* playfield_a)

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

    delete this->general;
    delete this->players;
    delete this->rules;

    this->backup_destroy();

    gtk_widget_destroy(this->notebook_);
    gtk_widget_destroy(this->button_reset);
    gtk_widget_destroy(this->button_bug_report_load);
    gtk_widget_destroy(this->button_start_party);
    gtk_widget_destroy(this->button_close);

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

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

      if (game_status == GAMESTATUS::PARTY_INIT) {
	gtk_widget_show(button_reset);
	gtk_widget_show(button_bug_report_load);
	gtk_widget_hide(button_close);
	gtk_widget_show(button_start_party);
      } else { // if (game_status == GAMESTATUS::PARTY_INIT)
	gtk_widget_show(button_reset);
	gtk_widget_hide(button_bug_report_load);
	gtk_widget_show(button_close);
	gtk_widget_hide(button_start_party);
      } // if else (game_status == GAMESTATUS::PARTY_INIT)

#ifdef RELEASE
      gtk_widget_hide(button_bug_report_load);
#endif

      this->general->sensitivity_update();
      this->players->sensitivity_update();
      this->rules->sensitivity_update();

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

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

      this->update();

      this->PlayfieldDialog::show();

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_SHOW,
		      "PartySettings::show()");
    } // void PartySettings::show()

  /**
   **
   ** event: reset all settings
   **
   ** @param	party_settings	the party settings
   **
   ** @return	-
   ** 
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::reset_event(GtkWidget*, gpointer party_settings)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		    "PartySettings::reset_event()");

      static_cast<PartySettings*>(party_settings)->reset();
      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_EVENT,
		      "PartySettings::reset_event()");
    } // static void PartySettings::reset_event(GtkWidget*, gpointer party_settings)

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

      this->general->backup();
      this->players->backup();
      this->rules->backup();

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

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

      this->general->backup_destroy();
      this->players->backup_destroy();
      this->rules->backup_destroy();

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

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

      this->general->reset();
      this->players->reset();
      this->rules->reset();

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

  /**
   **
   ** get party settings
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   ** @todo	put the main window in the foreground
   **
   **/
  void
    PartySettings::get()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_GAMEPLAY,
		    "PartySettings::get()");

      DEBUG_ASSERTION((::game_status == GAMESTATUS::PARTY_INIT),
		      "PartySettings::get()\n"
		      "  `game_status` != PARTY_INIT");

      this->backup();
      this->update();
      this->show();

      while ( (::game_status == GAMESTATUS::PARTY_INIT)
	      && (GTK_WIDGET_VISIBLE(this->window())) )
	gtk_main();

      this->close();
      this->players->aiconfigs().close();
      this->backup_destroy();

#ifndef POSTPHONED
      { // test the startseed with the value of the spin button
	unsigned const seed_first
	  = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(this->general->seed_random))
	     ? UINT_MAX
	     : static_cast<unsigned>(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(this->general->seed_value))));
	if (seed_first != ::party.seed_first()) {
#ifndef RELEASE
	  cerr << "PartySettings::get():\n"
	    << "seed_first != ::party.seed_first(): "
	    << seed_first << " != " << ::party.seed_first()
	    << endl;
#endif
	  ::party.seed_first_set(seed_first);
	} // if (seed_first != ::party.seed_first())
      } // test the startseed with the value of the spin button
#endif
      // *** put the main window in the foreground

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_GAMEPLAY,
		      "PartySettings::get()");
    } // void PartySettings::get()

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

      this->general->update();
      this->players->update();
      this->rules->update();

      this->sensitivity_update();

      this->language_update();


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

  /**
   **
   ** updates the name of the player
   **
   ** @param	player	player with the new name
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::name_update(::Player const& player)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_UPDATE,
		    "PartySettings::name_update(player)");


      this->general->language_update();
      this->players->name_update(player);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_UPDATE,
		      "PartySettings::name_update(player)");
    } // void PartySettings::name_update(::Player const& player)

  /**
   **
   ** updates the player
   **
   ** @param	player	player to be updated
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::player_update(::Player const& player)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_UPDATE,
		    "PartySettings::player_update(player)");


      this->general->language_update();
      this->players->player_update(player);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_SETTINGS && INFO_GTK_UPDATE,
		      "PartySettings::player_update(player)");
    } // void PartySettings::player_update(::Player const& player)

  /**
   **
   ** updates all language elements
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::language_update()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_SETTINGS && INFO_GTK_UPDATE,
		    "PartySettings::language_update()");

      this->general->language_update();
      this->players->language_update();
      this->rules->language_update();

      this->PlayfieldDialog::language_update();

      // button
      gtk_label_set_text(GTK_LABEL(GTK_BIN(this->button_reset)->child),
			 (" " + ::language("reset") + " ").c_str());
      gtk_label_set_text(GTK_LABEL(GTK_BIN(this->button_bug_report_load)->child),
			 (" " + ::language("load bug report") + " ").c_str());
      gtk_label_set_text(GTK_LABEL(GTK_BIN(this->button_start_party)->child),
			 (" " + ::language("start party") + " ").c_str());

      // labels of the tabs
      gtk_label_set_text(GTK_LABEL(this->label_general),
			 ::language("General").c_str());
      gtk_label_set_text(GTK_LABEL(this->label_players),
			 ::language("Players").c_str());
      gtk_label_set_text(GTK_LABEL(this->label_rules),
			 ::language("Rules").c_str());

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


  /**
   **
   ** key press
   **
   ** @param	key	pressed key
   **
   ** @return	-
   **
   ** @version	0.5.3
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::key(GdkEventKey* key)
    {
      DEBUG_CALLING(INFO_GTK_SETTINGS && INFO_GTK_KEY,
		    "PartySettings::key()");

#include <gdk/gdkkeysyms.h>

      if (key->state & GDK_CONTROL_MASK) {
	// with <Control>

	// toggle some windows
	switch (key->keyval) {
	case GDK_r: // reset the settings
	  this->reset();
	  break;
	default: // pass the key to the dialog
	  this->PlayfieldDialog::key(key);
	  break;
	} // switch (key->keyval)
      } else { // if !(key->state & GDK_CONTROL_MASK)
	// pass the key to the dialog
	this->PlayfieldDialog::key(key);
      } // if !(key->state & GDK_CONTROL_MASK)

      DEBUG_RETURNING(VOID,
		      INFO_GTK_SETTINGS && INFO_GTK_KEY,
		      "PartySettings::key()");
    } // void PartySettings::key(GdkKeyEvent);

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