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

#include "party_settings.h"
#include "players.h"
#include "aiconfigs.h"
#include "rules.h"

#include "ui.h"
#include "main_window.h"
#include "bug_report.h"

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

#include "widgets/stock_button.h"
#include <gtkmm/stock.h>
#include <gtkmm/radiobutton.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/notebook.h>
#include <gtkmm/label.h>
#include <gtkmm/alignment.h>
#include <gtkmm/frame.h>
#include <gtkmm/main.h>
#include <gtkmm/adjustment.h>
#include <gtkmm/table.h>
#include <gtkmm/fileselection.h>
namespace UI_GTKMM_NS {

  /**
   **
   ** Constructor
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   **/
  PartySettings::PartySettings(Base* const parent) :
    Base(parent),
  Dialog("PartySettings", *(parent->ui->main_window), false, true),
  players(NULL),
  rules(NULL),
  seed_bak(UINT_MAX),
  startplayer_first_bak(UINT_MAX),
  notebook(NULL),
  reset_button(NULL),
  load_bug_report_button(NULL),
  start_party_button(NULL),
  close_button(NULL),
  seed_value(NULL),
  seed_random(NULL),
  startplayer(),
  startplayer_random()
  {
    DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_INIT,
		  "PartySettings::PartySettings(parent)");

    this->init();
#if 0
    this->signal_realize().connect(SigC::slot(*this,
					      &PartySettings::language_update));
#endif

    this->signal_show().connect(SigC::slot(*this, &PartySettings::update));

    DEBUG_RETURNING(VOID,
		    INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_INIT,
		    "PartySettings::PartySettings(parent)");
  } // PartySettings::PartySettings(Base* const parent)

  /**
   **
   ** Destruktor
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   **/
  PartySettings::~PartySettings()
  {
    DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_INIT,
		  "PartySettings::~PartySettings()");

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

    DEBUG_RETURNING(VOID,
		    INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_INIT,
		    "PartySettings::~PartySettings()");
  } // PartySettings::~PartySettings()

  /**
   **
   ** create all subelements
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::init()
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_INIT,
		    "PartySettings::init()");

      this->ui->add_for_translation(*this, ::translator("Party settings"));

      this->set_icon(this->ui->main_window->icon);

      this->set_position(Gtk::WIN_POS_CENTER_ON_PARENT);

      this->players = new Players(this);
      this->rules = new Rules(this);
      this->notebook = Gtk::manage(new Gtk::Notebook());

      // the action buttons
      this->reset_button
	= Gtk::manage(new Gtk::StockButton(Gtk::Stock::UNDO,
					   "reset"));
      this->add_action_widget(*(this->reset_button), Gtk::RESPONSE_REJECT);
      this->load_bug_report_button
	= Gtk::manage(new Gtk::StockButton(Gtk::Stock::OPEN,
					   "load bug report"));
#ifndef RELEASE
      this->add_action_widget(*(this->load_bug_report_button),
			      Gtk::RESPONSE_NONE);
#endif
      this->start_party_button
	= Gtk::manage(new Gtk::StockButton(Gtk::Stock::OK,
					   "start party"));
      this->add_action_widget(*(this->start_party_button), Gtk::RESPONSE_CLOSE);
      this->close_button
	= Gtk::manage(new Gtk::StockButton(Gtk::Stock::CLOSE,
					   "close"));
      this->add_action_widget(*(this->close_button), Gtk::RESPONSE_CLOSE);

      // the elements in the tab 'general'
      this->seed_value = Gtk::manage(new Gtk::SpinButton(1, 0));
      this->seed_random = Gtk::manage(new Gtk::CheckButton("random"));
      this->startplayer_random = Gtk::manage(new Gtk::RadioButton("random"));


      this->start_party_button->grab_default();

      this->get_vbox()->add(*(this->notebook));
      this->seed_value->set_range(0, PSEUDO_RAND_MAX);
      this->seed_value->set_increments(1, 1000);

      this->ui->add_for_translation(*(this->reset_button->label),
				    ::translator("reset"));
      this->ui->add_for_translation(*(this->load_bug_report_button->label),
				    ::translator("load bug report"));
      this->ui->add_for_translation(*(this->start_party_button->label),
				    ::translator("start party"));
      this->ui->add_for_translation(*(this->close_button->label),
				    ::translator("close"));

      this->ui->add_for_translation(*(static_cast<Gtk::Label*>(this->seed_random->get_child())),
				    ::translator("random"));
      this->ui->add_for_translation(*(static_cast<Gtk::Label*>(this->startplayer_random->get_child())),
				    ::translator("random"));

      { // create the startplayer buttons
	Gtk::RadioButton::Group startplayer_group
	  = this->startplayer_random->get_group();
	for (unsigned  p = 0; p < ::party.playerno(); p++)
	  this->startplayer.push_back(Gtk::manage(new Gtk::RadioButton(startplayer_group,
								       Glib::locale_to_utf8(::party.player(p).name())))
				     );
      } // create the startplayer buttons
      { // set the pages of the notebook
	{ // General
	  Gtk::Alignment* alignment
	    = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
					     Gtk::ALIGN_CENTER,
					     0, 0));
	  alignment->set_border_width(20);
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("General"));
	  this->ui->add_for_translation(*label, ::translator("General"));
	  this->notebook->append_page(*alignment, *label);

	  Gtk::VBox* vbox = Gtk::manage(new Gtk::VBox(false, 20));
	  alignment->add(*vbox);

	  { // seed
	    Gtk::Frame* seed_frame = Gtk::manage(new Gtk::Frame("Game seed"));
	    this->ui->add_for_translation(*(dynamic_cast<Gtk::Label*>(seed_frame->get_label_widget())),
					  ::translator("Game seed"));
	    vbox->add(*seed_frame);

	    Gtk::VBox* vbox2 = Gtk::manage(new Gtk::VBox(false, 10));
	    seed_frame->add(*vbox2);
	    vbox2->set_border_width(20);

	    Gtk::Alignment* alignment2
	      = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
					       Gtk::ALIGN_CENTER,
					       0, 0));
	    vbox2->add(*alignment2);
	    alignment2->add(*(this->seed_value));

	    alignment2
	      = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
					       Gtk::ALIGN_CENTER,
					       0, 0));
	    vbox2->add(*alignment2);
	    alignment2->add(*(this->seed_random));
	  } // seed

	  { // startplayer
	    Gtk::Frame* startplayer_frame
	      = Gtk::manage(new Gtk::Frame("Startplayer"));
	    this->ui->add_for_translation(*(dynamic_cast<Gtk::Label*>(startplayer_frame->get_label_widget())),
					  ::translator("Startplayer"));
	    vbox->add(*startplayer_frame);

	    Gtk::Table* startplayer_table
	      = Gtk::manage(new Gtk::Table(3, 3, true));
	    startplayer_frame->add(*startplayer_table);
	    startplayer_table->set_border_width(20);
	    startplayer_table->set_spacings(10);
	    startplayer_table->attach(*(this->startplayer_random), 1, 2, 1, 2);
	    startplayer_table->attach(*(this->startplayer[0]), 1, 2, 2, 3);
	    startplayer_table->attach(*(this->startplayer[1]), 0, 1, 1, 2);
	    startplayer_table->attach(*(this->startplayer[2]), 1, 2, 0, 1);
	    startplayer_table->attach(*(this->startplayer[3]), 2, 3, 1, 2);
	  } // startplayer

	} // General
	{ // Players
	  Gtk::Alignment* alignment
	    = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
					     Gtk::ALIGN_CENTER,
					     0, 0));
	  alignment->set_border_width(20);
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("Players"));
	  this->ui->add_for_translation(*label, ::translator("Players"));
	  this->notebook->append_page(*(this->players), *label);

	} // Players
	{ // Rules
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("Rules"));
	  this->ui->add_for_translation(*label, ::translator("Rules"));
	  this->notebook->append_page(*(this->rules->container), *label);

	} // Rules
      } // set the pages of the notebook

      // signals
      this->reset_button->signal_clicked().connect(SigC::slot(*this,
							      &PartySettings::reset)
						  );
      this->load_bug_report_button->signal_clicked().connect(SigC::slot(*this,
									&PartySettings::load_bug_report)
							    );
      this->start_party_button->signal_clicked().connect(SigC::slot(*this,
								    &Gtk::Widget::hide)
							);
      this->close_button->signal_clicked().connect(SigC::slot(*this,
							      &Gtk::Widget::hide)
						  );

      this->seed_random->signal_toggled().connect(SigC::slot(*this,
							     &PartySettings::seed_value_sensitivity_update)
						 );

      this->signal_hide().connect(SigC::slot(*(this->ui->bug_report->load_file_selector),
					     &Gtk::Widget::hide));

      this->show_all_children();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_INIT,
		      "PartySettings::init()");
    } // void PartySettings::init()

  /**
   **
   ** creates a backup
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::create_backup()
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_VALUE,
		    "PartySettings::create_backup()");

      this->seed_bak = ::party.seed_first();
      this->startplayer_first_bak = ::party.startplayer_first();

      this->players->create_backup();
      this->rules->create_backup();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_VALUE,
		      "PartySettings::create_backup()");
    } // void PartySettings::create_backup()

  /**
   **
   ** resets the party settings
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::reset()
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_UPDATE,
		    "PartySettings::reset()");

      ::party.seed_set(this->seed_bak);
      ::party.startplayer_first_set(this->startplayer_first_bak);

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

      this->update();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_UPDATE,
		      "PartySettings::reset()");
    } // void PartySettings::reset()

  /**
   **
   ** get the party settings
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.0
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::get()
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_GAMEPLAY,
		    "PartySettings::get()");

      this->create_backup();

      this->update();

      this->notebook->set_current_page(0);

      this->present();

      while ((::game_status == GAMESTATUS::PARTY_INIT)
	     && (this->is_visible()))
	Gtk::Main::iteration();

      // set the seed
      if (this->seed_random->get_active())
	::party.seed_first_set(UINT_MAX);
      else
	::party.seed_first_set(this->seed_value->get_value_as_int());

      // set the startplayer
      if (this->startplayer_random->get_active())
	::party.startplayer_first_set_random();
      else
	for (unsigned p = 0; p < ::party.playerno(); ++p)
	  if (this->startplayer[p]->get_active()) {
	    ::party.startplayer_first_set(p);
	    break;
	  }

      if (this->players->aiconfigs != NULL)
	this->players->aiconfigs->hide();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_GAMEPLAY,
		      "PartySettings::get()");
    } // void PartySettings::get()

  /**
   **
   ** show the window.
   ** Shows/hides the action buttons
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::on_show()
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_EVENT,
		    "PartySettings::show()");

      this->Dialog::on_show();

      this->update();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_EVENT,
		      "PartySettings::show()");
    } // void PartySettings::show()

  /**
   **
   ** load the bug report
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::load_bug_report()
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_EVENT,
		    "PartySettings::load_bug_report()");

      this->ui->bug_report->load_file_selector->show();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_EVENT,
		      "PartySettings::load_bug_report()");
    } // void PartySettings::load_bug_report()

  /**
   **
   ** show the rules
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.0
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::show_rules()
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_SHOW,
		    "PartySettings::show_rules()");

      this->notebook->set_current_page(2);
      this->present();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_SHOW,
		      "PartySettings::show_rules()");
    } // void PartySettings::show_rules()

  /**
   **
   ** update the sensitivity of all elements
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.0
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::sensitivity_update()
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_EVENT,
		    "PartySettings::sensitivity_update()");

      if (::game_status == GAMESTATUS::PARTY_INIT) {
	this->seed_value_sensitivity_update();
	this->seed_random->set_sensitive(true);

	for (vector<Gtk::RadioButton*>::iterator p = this->startplayer.begin();
	     p != this->startplayer.end();
	     p++)
	  (*p)->set_sensitive(true);
	this->startplayer_random->set_sensitive(true);

      } else { // if !(::game_status == GAMESTATUS::PARTY_INIT)
	this->seed_value->set_sensitive(false);
	this->seed_random->set_sensitive(false);

	for (vector<Gtk::RadioButton*>::iterator p = this->startplayer.begin();
	     p != this->startplayer.end();
	     p++)
	  (*p)->set_sensitive(false);
	this->startplayer_random->set_sensitive(false);
      } // if !(::game_status == GAMESTATUS::PARTY_INIT)

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

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_EVENT,
		      "PartySettings::sensitivity_update()");
    } // void PartySettings::sensitivity_update()

  /**
   **
   ** update the sensitivity of 'seed_value'
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.0
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::seed_value_sensitivity_update()
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_EVENT,
		    "PartySettings::seed_value_sensitivity_update()");

      if (::game_status == GAMESTATUS::PARTY_INIT)
	this->seed_value->set_sensitive(!(this->seed_random->get_active()));
      else
	this->seed_value->set_sensitive(false);

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_EVENT,
		      "PartySettings::seed_value_sensitivity_update()");
    } // void PartySettings::seed_value_sensitivity_update()

  /**
   **
   ** update the widgets
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::update()
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_UPDATE,
		    "PartySettings::update()");

      if (!this->is_visible())
	DEBUG_RETURNING(VOID,
			INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_UPDATE,
			"PartySettings::update()");

      this->sensitivity_update();

      if (::game_status == GAMESTATUS::PARTY_INIT) {
	this->reset_button->show();
	this->load_bug_report_button->show();
	this->start_party_button->show();
	this->close_button->hide();

	this->start_party_button->grab_default();
      } else { // if !(::game_status == GAMESTATUS::PARTY_INIT)
	this->reset_button->hide();
	this->load_bug_report_button->hide();
	this->start_party_button->hide();
	this->close_button->show();

	this->close_button->grab_default();
      } // if !(::game_status == GAMESTATUS::PARTY_INIT)

      bool const random_seed = (::party.seed_first() == UINT_MAX);
      this->seed_value->set_value(random_seed
				  ? 0
				  : ::party.seed_first());
      this->seed_random->set_active(random_seed);

      if (::party.startplayer_first() == UINT_MAX)
	this->startplayer_random->set_active(true);
      else
	this->startplayer[::party.startplayer_first()]->set_active(true);

      this->players->update();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_UPDATE,
		      "PartySettings::update()");
    } // void PartySettings::update()

  /**
   **
   ** update 'player'
   **
   ** @param	player	player to update
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::player_update(Player const& player)
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_UPDATE,
		    "PartySettings::player_update(player)");

      this->name_update_local(player);

      this->players->player_update(player);

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

  /**
   **
   ** update the name of 'player'
   **
   ** @param	player	player with the new name
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::name_update(Player const& player)
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_UPDATE,
		    "PartySettings::name_update(player)");

      this->name_update_local(player);
      this->players->name_update(player);

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

  /**
   **
   ** update the name of 'player'
   **
   ** @param	player	player with the new name
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    PartySettings::name_update_local(Player const& player)
    {
      DEBUG_CALLING(INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_UPDATE,
		    "PartySettings::name_update_local(player)");

      this->startplayer[player.no()]->set_label(Glib::locale_to_utf8(player.name()));

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PARTY_SETTINGS && INFO_GTKMM_UPDATE,
		      "PartySettings::name_update_local(player)");
    } // void PartySettings::name_update_local(Player const& player)

} // namespace UI_GTKMM_NS

#endif // #ifdef USE_UI_GTKMM
