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

#include "../../party/party.h"
#include "../../player/aiconfig.h"
#include "../../misc/setting.h"
#ifdef WINDOWS
#include "../../utils/string.h"
#endif

#include "widgets/labelscalespinbutton.h"
#include "widgets/filemenu.h"
#include "widgets/stock_button.h"
#include <gtkmm/stock.h>
#include <gtkmm/label.h>
#include <gtkmm/box.h>
#include <gtkmm/table.h>
#include <gtkmm/checkbutton.h>
#include <gtkmm/fileselection.h>
#include <gtkmm/main.h>

namespace UI_GTKMM_NS {

  /**
   **
   ** Constructor
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   **/
  Players::AiConfigs::AiConfig::AiConfig(AiConfigs* const aiconfigs,
					 unsigned const playerno) :
    Base(aiconfigs),
  Notebook(),
  aiconfigs(aiconfigs),
  players(aiconfigs->players),
  playerno_(playerno),
  name_bookmark(Gtk::manage(new Gtk::Label(Glib::locale_to_utf8(this->player().name())))),
  container(Gtk::manage(new Gtk::VBox())),
  hardcoded_button(NULL),
  adopt_button(NULL),
  allot_button(NULL),
  load_button(NULL),
  save_button(NULL),
  save_file_selector(NULL),
  aitype(),
  type_bool(),
  type_unsigned()
  {
    DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_INIT,
		  "Players::AiConfigs::AiConfig::AiConfig(aiconfigs)");

#ifdef POSTPHONED
    this->signal_realize().connect(SigC::slot(*this, &Players::AiConfigs::AiConfig::init));
#else
    this->init();
    this->signal_realize().connect(SigC::slot(*this, &Players::AiConfigs::AiConfig::language_update));
    this->signal_realize().connect(SigC::slot(*this, &Players::AiConfigs::AiConfig::update));
    this->signal_realize().connect(SigC::slot(*this, &Players::AiConfigs::AiConfig::sensitivity_update));
#endif

    DEBUG_RETURNING(VOID,
		    INFO_GTKMM_AICONFIG && INFO_GTKMM_INIT,
		    "Players::AiConfigs::AiConfig::AiConfig(aiconfigs)");
  } // Players::AiConfigs::AiConfig::AiConfig(AiConfigs* const aiconfigs)

  /**
   **
   ** Destruktor
   **
   ** @param	-
   **
   ** @return	-
   ** 
   ** @author	Diether Knof
   **
   ** @version	0.5.4
   **
   **/
  Players::AiConfigs::AiConfig::~AiConfig()
  {
    DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_INIT,
		  "Players::AiConfigs::AiConfig::~AiConfig()");

    for (vector<Gtk::RadioButton*>::iterator i = this->aitype.begin();
	 i != this->aitype.end();
	 i++)
      delete static_cast<string*>((*i)->steal_data("type"));

    for (vector<Gtk::CheckButton*>::iterator i = this->type_bool.begin();
	 i != this->type_bool.end();
	 i++)
      delete static_cast<string*>((*i)->steal_data("type"));

    for (vector<Gtk::LabelSpinButton*>::iterator i
	 = this->type_unsigned.begin();
	 i != this->type_unsigned.end();
	 i++)
      delete static_cast<string*>((*i)->steal_data("type"));

    DEBUG_RETURNING(VOID,
		    INFO_GTKMM_AICONFIG && INFO_GTKMM_INIT,
		    "Players::AiConfigs::AiConfig::~AiConfig()");
  } // Players::AiConfigs::AiConfig::~AiConfig()

  /**
   **
   ** creates all subelements
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::init()
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_INIT,
		    "Players::AiConfigs::AiConfig::init()");

      this->hardcoded_button
	= Gtk::manage(new Gtk::StockButton("hardcoded"));
      this->ui->add_for_translation(*(this->hardcoded_button),
				    ::translator("hardcoded"));
      this->adopt_button
	= Gtk::manage(new Gtk::StockButton("adopt"));
      this->ui->add_for_translation(*(this->adopt_button),
				    ::translator("adopt"));
      this->allot_button
	= Gtk::manage(new Gtk::StockButton("allot"));
      this->ui->add_for_translation(*(this->allot_button),
				    ::translator("allot"));
      this->load_button
	= Gtk::manage(new Gtk::StockButton("load"));
      this->ui->add_for_translation(*(this->load_button),
				    ::translator("load"));
      this->save_button
	= Gtk::manage(new Gtk::StockButton(Gtk::Stock::SAVE_AS, "save"));
      this->ui->add_for_translation(*(this->save_button),
				    ::translator("save"));
      this->save_file_selector = new Gtk::FileSelection("Save aiconfig");
      this->ui->add_for_translation(*(this->save_file_selector),
				    ::translator("Save aiconfig of %splayer%",
						 this->player().name()));

      this->container->pack_start(*this, true, true);

#ifndef WINDOWS
      this->save_file_selector->set_filename(::setting(Setting::PRIVATE_DATA_DIRECTORY)
					     + "/"
					     + ::setting(Setting::AI_DIRECTORY)
					     + "/");
#else // #ifndef WINDOWS
      {
	string filename = (::setting(Setting::PRIVATE_DATA_DIRECTORY)
			   + "/"
			   + ::setting(Setting::AI_DIRECTORY)
			   + "/"
			  );
	DK::Utils::String::replace_all(filename, "/", "\\");
	this->save_file_selector->set_filename(filename);
      }
#endif // #ifndef WINDOWS

      { // create the buttons
	Gtk::RadioButton::Group aitype_group;
	for (int t = AITYPE::AITYPE_FIRST; t <= AITYPE::AITYPE_LAST; t++) {
	  this->aitype.push_back(Gtk::manage(new Gtk::RadioButton(aitype_group,
								  ::name(AiType(t)))));
	  this->aitype.back()->set_data("type", new AiType(AiType(t)));
	  this->ui->add_for_translation(*(this->aitype.back()),
					::translator(::name(AiType(t))));
	  this->aitype.back()->signal_toggled().connect(SigC::bind<int const>(SigC::slot(*this, &AiConfig::aitype_change),
									      t)
						       );
	}
	for (int t = Aiconfig::BOOL_FIRST; t <= Aiconfig::BOOL_LAST; t++) {
	  this->type_bool.push_back(Gtk::manage(new Gtk::CheckButton(::name(Aiconfig::TypeBool(t)))));
	  this->type_bool.back()->set_data("type", new Aiconfig::TypeBool(Aiconfig::TypeBool(t)));
	  this->ui->add_for_translation(*(this->type_bool.back()),
					::translator(::name(Aiconfig::TypeBool(t))));
	  this->type_bool.back()->signal_toggled().connect(SigC::bind<int const>(SigC::slot(*this, &AiConfig::change),
										 t)
							  );
	} // for (t \in Aiconfig::TypeBool)
	for (int t = Aiconfig::UNSIGNED_FIRST; t <= Aiconfig::UNSIGNED_LAST; t++) {
	  switch (t) {
	  case Aiconfig::REMEMBERTRICKS:
	  case Aiconfig::LASTFEHLCREATION:
	  case Aiconfig::LASTHEURISTICTRICK:
	    this->type_unsigned.push_back(Gtk::manage(new Gtk::LabelScaleSpinButton()));
	    break;
	  case Aiconfig::LIMITQUEEN:
	  case Aiconfig::LIMITDOLLE:
	  case Aiconfig::ANNOUNCELIMIT:
	  case Aiconfig::ANNOUNCELIMITDEC:
	  case Aiconfig::ANNOUNCECONFIG:
	  case Aiconfig::ANNOUNCELIMITREPLY:
	  case Aiconfig::ANNOUNCECONFIGREPLY:
	  case Aiconfig::TAKEPOVERTY:
	  case Aiconfig::SINGLESOLO:
	  case Aiconfig::DOUBLESOLO:
	  case Aiconfig::TRIPLESOLO:
	  case Aiconfig::COLORSOLO:
	  case Aiconfig::MEATLESS:
	  case Aiconfig::FUTURE_LIMIT:
	    this->type_unsigned.push_back(Gtk::manage(new Gtk::LabelSpinButton(::name(Aiconfig::TypeUnsigned(t)))));
	    break;
	  } // switch(t)
	  this->type_unsigned.back()->set_data("type", new Aiconfig::TypeUnsigned(Aiconfig::TypeUnsigned(t)));
	  this->ui->add_for_translation(this->type_unsigned.back()->get_label(),
					::translator("%ttranslation%: ",
						     ::translator(::name(Aiconfig::TypeUnsigned(t)))));
	  this->type_unsigned.back()->signal_value_changed().connect(SigC::bind<int const>(SigC::slot(*this, &AiConfig::change),
											   t)
								    );
	  switch(t) {
	  case Aiconfig::FUTURE_LIMIT:
	    this->type_unsigned.back()->get_spin_button().set_increments(1, 1000);
	    break;
	  default:
	    break;
	  } // switch(t)
	} // for (t \in Aiconfig::TypeUnsigned)
      } // create the buttons

      { // the buttons for loading/saving
	Gtk::Table* table = Gtk::manage(new Gtk::Table(3, 2, true));
	table->set_spacings(1 ex);
	this->container->pack_end(*table, false, true);

	table->attach(*(this->hardcoded_button), 0, 2, 0, 1);
	table->attach(*(this->adopt_button), 0, 1, 1, 2);
	table->attach(*(this->allot_button), 1, 2, 1, 2);
	table->attach(*(this->load_button), 0, 1, 2, 3);
	table->attach(*(this->save_button), 1, 2, 2, 3);
      } // the buttons for loading/saving

      { // the notebook pages
	Gtk::Alignment* alignment = NULL;
	Gtk::VBox* vbox = NULL;
	{ // simple settings
	  alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						     Gtk::ALIGN_CENTER,
						     0, 0));
	  alignment->set_border_width(1 em);
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("simple"));
	  this->ui->add_for_translation(*label,
					::translator("simple"));
	  this->append_page(*alignment, *label);

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

	  vbox->add(*(this->type_bool[Aiconfig::FAIRPLAYHANDS - Aiconfig::BOOL_FIRST]));
	  vbox->add(*(this->type_bool[Aiconfig::FAIRPLAYTEAMS - Aiconfig::BOOL_FIRST]));
	  vbox->add(*(this->type_bool[Aiconfig::TRUSTING - Aiconfig::BOOL_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::REMEMBERTRICKS - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::FUTURE_LIMIT - Aiconfig::UNSIGNED_FIRST]));
	} // simple settings
	{ // aitype
	  alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						     Gtk::ALIGN_CENTER,
						     0, 0));
	  alignment->set_border_width(1 em);
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("aitype"));
	  this->ui->add_for_translation(*label,
					::translator("aitype"));
	  this->append_page(*alignment, *label);

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

	  for (int t = AITYPE::AITYPE_FIRST + 1; t <= AITYPE::AITYPE_LAST; t++)
	    vbox->add(*(this->aitype[t - AITYPE::AITYPE_FIRST]));
	} // aitype
	{ // announcement
	  alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						     Gtk::ALIGN_CENTER,
						     0, 0));
	  alignment->set_border_width(1 em);
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("announcement"));
	  this->ui->add_for_translation(*label,
					::translator("announcement"));
	  this->append_page(*alignment, *label);

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

	  vbox->add(*(this->type_unsigned[Aiconfig::ANNOUNCELIMIT - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::ANNOUNCELIMITDEC - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::ANNOUNCECONFIG - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::ANNOUNCELIMITREPLY - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::ANNOUNCECONFIGREPLY - Aiconfig::UNSIGNED_FIRST]));
	} // announcement
	{ // trick decision
	  alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						     Gtk::ALIGN_CENTER,
						     0, 0));
	  alignment->set_border_width(1 em);
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("trick decision"));
	  this->ui->add_for_translation(*label,
					::translator("trick decision"));
	  this->append_page(*alignment, *label);

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

	  vbox->add(*(this->type_bool[Aiconfig::FEHLCREATIONONFIRSTCARD - Aiconfig::BOOL_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::LASTHEURISTICTRICK - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::LASTFEHLCREATION - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::LIMITQUEEN - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::LIMITDOLLE - Aiconfig::UNSIGNED_FIRST]));
	} // trick decision
	{ // game decision
	  alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						     Gtk::ALIGN_CENTER,
						     0, 0));
	  alignment->set_border_width(1 em);
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("game decision"));
	  this->ui->add_for_translation(*label,
					::translator("game decision"));
	  this->append_page(*alignment, *label);

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

	  vbox->add(*(this->type_unsigned[Aiconfig::TAKEPOVERTY - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::SINGLESOLO - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::DOUBLESOLO - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::TRIPLESOLO - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::COLORSOLO - Aiconfig::UNSIGNED_FIRST]));
	  vbox->add(*(this->type_unsigned[Aiconfig::MEATLESS - Aiconfig::UNSIGNED_FIRST]));
	} // game decision
	{ // the heuristics
	  Gtk::Notebook* notebook = Gtk::manage(new Gtk::Notebook());
	  Gtk::Label* label = Gtk::manage(new Gtk::Label("heuristics"));
	  this->ui->add_for_translation(*label,
					::translator("heuristics"));
	  this->append_page(*notebook, *label);

	  { // normal game
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("normal game"));
	    this->ui->add_for_translation(*label,
					  ::translator("normal game"));
	    notebook->append_page(*alignment, *label);

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

	    vbox->add(*(this->type_bool[Aiconfig::CHOOSE_ACE - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::CHOOSE_FOR_COLOR_TRICK - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::CHOOSE_PFUND - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::JAB_FOR_ACE - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::CREATE_FEHL - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::BEST_WINNING - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::LOW_HIGH - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::PLAY_FOR_TEAM - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::JAB_FOX - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::DRAW_TRUMP - Aiconfig::BOOL_FIRST]));
	  } // normal game
	  { // color solo
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("color solo"));
	    this->ui->add_for_translation(*label,
					  ::translator("color solo"));
	    notebook->append_page(*alignment, *label);

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

	    vbox->add(*(this->type_bool[Aiconfig::COLOR_CHOOSE_ACE - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::COLOR_BEST_WINNING - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::COLOR_JAB_FOR_ACE - Aiconfig::BOOL_FIRST]));
	    vbox->add(*(this->type_bool[Aiconfig::COLOR_LOW_HIGH - Aiconfig::BOOL_FIRST]));
	  } // color solo
	  { // picture solo
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("picture solo"));
	    this->ui->add_for_translation(*label,
					  ::translator("picture solo"));
	    notebook->append_page(*alignment, *label);

	    vbox = Gtk::manage(new Gtk::VBox(false, 1 em));
	    alignment->add(*vbox);
	    vbox->add(*(this->type_bool[Aiconfig::PICTURE_SECONDBESTTRUMP - Aiconfig::BOOL_FIRST]));
	  } // picture solo
	  { // meatless solo
	    alignment = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_CENTER,
						       Gtk::ALIGN_CENTER,
						       0, 0));
	    alignment->set_border_width(1 em);
	    Gtk::Label* label = Gtk::manage(new Gtk::Label("meatless solo"));
	    this->ui->add_for_translation(*label,
					  ::translator("meatless solo"));
	    notebook->append_page(*alignment, *label);

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

	    vbox->add(*(this->type_bool[Aiconfig::MEATLESS_PLAYHIGHESTCOLOR - Aiconfig::BOOL_FIRST]));
	  } // meatless solo
	} // the heuristics
      } // the notebook pages

      // the signals
      this->hardcoded_button->signal_clicked().connect(SigC::slot(*this, &AiConfig::hardcoded));
      this->adopt_button->signal_clicked().connect(SigC::slot(*this, &AiConfig::adopt));
      this->allot_button->signal_clicked().connect(SigC::slot(*this, &AiConfig::allot));
      this->load_button->signal_clicked().connect(SigC::slot(*this, &AiConfig::load));
      this->save_button->signal_clicked().connect(SigC::slot(*(this->save_file_selector), &Widget::show));

      this->save_file_selector->get_cancel_button()->signal_clicked().connect(SigC::slot(*(this->save_file_selector), &Widget::hide));
      this->save_file_selector->get_ok_button()->signal_clicked().connect(SigC::slot(*(this->save_file_selector), &Widget::hide));
      this->save_file_selector->get_ok_button()->signal_clicked().connect(SigC::slot(*this, &AiConfig::save));


      this->update();
      this->sensitivity_update();

      this->container->show_all();

      this->language_update();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_INIT,
		      "Players::AiConfigs::AiConfig::init()");
    } // void Players::AiConfigs::AiConfig::init()

  /**
   **
   ** signal: show the setting page
   **
   ** @param	page	new page
   ** @param	pageno	page to show
   **
   ** @return	-
   **
   ** @version	0.6.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::on_switch_page(GtkNotebookPage* page,
						 guint pageno)
    {
      DEBUG_CALLING(INFO_GTKMM_PLAYERS && INFO_GTKMM_UPDATE,
		    "Players::AiConfigs::AiConfig::on_switch_page(page, pageno)");

      if (static_cast<unsigned>(this->get_current_page()) != pageno) {
	this->Notebook::on_switch_page(page, pageno);

	if (this->is_realized())
	  for (unsigned p = 0; p < ::party.playerno(); ++p)
	    this->aiconfigs->aiconfig(p).set_current_page(pageno);
      }

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_PLAYERS && INFO_GTKMM_UPDATE,
		      "Players::AiConfigs::AiConfig::on_switch_page(page, pageno)");
    } // void Players::AiConfigs::AiConfig::on_switch_page(GtkNotebookPage* page, guint pageno)

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the player
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  ::Player&
    Players::AiConfigs::AiConfig::player()
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_VALUE,
		    "Players::AiConfigs::AiConfig::player()");

      DEBUG_RETURNING(::party.player(this->playerno()),
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_VALUE,
		      "Players::AiConfigs::AiConfig::player()");
    } // ::Player& Players::AiConfigs::AiConfig::player()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the ai configuration
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  ::Aiconfig&
    Players::AiConfigs::AiConfig::aiconfig()
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_VALUE,
		    "Players::AiConfigs::AiConfig::aiconfig()");

      DEBUG_RETURNING(dynamic_cast<Aiconfig&>(this->player()),
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_VALUE,
		      "Players::AiConfigs::AiConfig::aiconfig()");
    } // ::Aiconfig& Players::AiConfigs::AiConfig::aiconfig()

  /**
   **
   ** -> result
   **
   ** @param	-
   **
   ** @return	the playernumber
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  unsigned
    Players::AiConfigs::AiConfig::playerno() const
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_VALUE,
		    "Players::AiConfigs::AiConfig::playerno()");

      DEBUG_RETURNING(this->playerno_,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_VALUE,
		      "Players::AiConfigs::AiConfig::playerno()");
    } // unsigned Players::AiConfigs::AiConfig::playerno() const

  /**
   **
   ** the aitype has been changed by the user
   **
   ** @param	type	the new aitype
   **
   ** @return	-
   **
   ** @version	0.6
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::aitype_change(int const type)
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		    "AiConfig::aitype_change(type)");

      if (this->aitype[type - AITYPE::AITYPE_FIRST]->get_active() == true)
	this->aiconfig().aitype_set(AiType(type));

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		      "AiConfig::aitype_change(type)");
    } // void Players::AiConfigs::AiConfig::aitype_change(int const type)

  /**
   **
   ** a aiconfig has been changed by the user
   **
   ** @param	type	the type of the aiconfig
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::change(int const type)
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		    "AiConfig::change(type)");

      if ((type >= Aiconfig::BOOL_FIRST)
	  && (type <= Aiconfig::BOOL_LAST))
	this->aiconfig().set(Aiconfig::TypeBool(type),
			     this->type_bool[type - Aiconfig::BOOL_FIRST]->get_active());
      else if ((type >= Aiconfig::UNSIGNED_FIRST)
	       && (type <= Aiconfig::UNSIGNED_LAST)) {
	if (this->type_unsigned[type - Aiconfig::UNSIGNED_FIRST]->is_realized())
	  this->aiconfig().set(Aiconfig::TypeUnsigned(type),
			       this->type_unsigned[type - Aiconfig::UNSIGNED_FIRST]->get_value_as_int());
      }
      else 
	DEBUG_ASSERTION(false,
			"AiConfig::change(type):\n"
			"  type '" << type << "' unknown.");

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		      "AiConfig::change(type)");
    } // void Players::AiConfigs::AiConfig::change(int const type)

  /**
   **
   ** sets the ai to the hardcoded
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::hardcoded()
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		    "Players::AiConfigs::AiConfig::hardcoded()");

      this->aiconfig().reset_to_hardcoded();
      this->update();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		      "Players::AiConfigs::AiConfig::hardcoded()");
    } // void Players::AiConfigs::AiConfig::hardcoded()

  /**
   **
   ** creates a menu with the players to adopt from
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::adopt()
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		    "Players::AiConfigs::AiConfig::adopt()");


      Gtk::Menu* adopt_menu
	= Gtk::manage(new Gtk::Menu());
      adopt_menu->add(*(Gtk::manage(new Gtk::TearoffMenuItem())));

      for (unsigned p = 0; p < ::party.playerno(); p++)
	if (p != this->player().no()) {
	  Gtk::MenuItem* item
	    = Gtk::manage(new Gtk::MenuItem(Glib::locale_to_utf8(this->aiconfigs->aiconfig(p).player().name())));
	  item->signal_activate().connect(SigC::bind<unsigned const>(SigC::slot(*this, &AiConfig::adopt_aiconfig), p));
	  adopt_menu->append(*item);
	} // if (p != this->player().playerno())

      adopt_menu->show_all();
      adopt_menu->popup(0, 0);

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		      "Players::AiConfigs::AiConfig::adopt()");
    } // void Players::AiConfigs::AiConfig::adopt()

  /**
   **
   ** adopt the aiconfig from player 'playerno'
   **
   ** @param	playerno	player to adopt from
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::adopt_aiconfig(unsigned const playerno)
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		    "AiConfig::adopt_aiconfig(playerno)");

      if (::game_status == GAMESTATUS::PARTY_INIT) {
	this->aiconfig() = this->aiconfigs->aiconfig(playerno).aiconfig();
	this->update();
      } // if (::game_status == GAMESTATUS::PARTY_INIT)

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		      "AiConfig::adopt_aiconfig(playerno)");
    } // void Players::AiConfigs::AiConfig::adopt_aiconfig(unsigned const playerno)

  /**
   **
   ** make all other aiconfigs like this
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::allot()
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		    "AiConfig::allot()");

      for (unsigned p = 0; p < ::party.playerno(); p++)
	if (p != this->playerno())
	  this->aiconfigs->aiconfig(p).adopt_aiconfig(this->playerno());

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		      "AiConfig::allot()");
    } // void Players::AiConfigs::AiConfig::allot()

  /**
   **
   ** creates a menu with the files in the aiconfig directories
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::load()
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		    "Players::AiConfigs::AiConfig::load()");


      Gtk::FileMenu* load_menu
	= Gtk::manage(new Gtk::FileMenu(SigC::slot(*this, &AiConfig::load_file)));
      load_menu->add_directory(::setting(Setting::PRIVATE_DATA_DIRECTORY)
			       + "/"
			       + ::setting(Setting::AI_DIRECTORY));
      load_menu->add_directory(::setting(Setting::PUBLIC_DATA_DIRECTORY)
			       + "/"
			       + ::setting(Setting::AI_DIRECTORY));

      load_menu->show();

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		      "Players::AiConfigs::AiConfig::load()");
    } // void Players::AiConfigs::AiConfig::load()

  /**
   **
   ** loads the aiconfig
   **
   ** @param	filename	the aiconfig file
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::load_file(string const filename)
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		    "Players::AiConfigs::AiConfig::load_file(filename)");

      if (::game_status == GAMESTATUS::PARTY_INIT) {
	this->aiconfig().load(filename);
	this->update();
      } // if (::game_status == GAMESTATUS::PARTY_INIT)

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		      "Players::AiConfigs::AiConfig::load_file(filename)");
    } // void Players::AiConfigs::AiConfig::load_file(string const filename)

  /**
   **
   ** saves the aiconfig.
   ** The filename is taken from 'save_file_selector'.
   **
   ** @param	filename	the aiconfig file
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::save()
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		    "AiConfig::save()");

      this->aiconfig().save(this->save_file_selector->get_filename()); 

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_EVENT,
		      "AiConfig::save()");
    } // void Players::AiConfigs::AiConfig::save()

  /**
   **
   ** update the sensitivity of all widgets
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.6.0
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::sensitivity_update()
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_UPDATE,
		    "Players::AiConfigs::AiConfig::sensitivity_update()");

#ifdef RELEASE
      if (::game_status == GAMESTATUS::PARTY_INIT)
#else
	;
      // be carful when changing the ai during the game
      if (true)
#endif
      {
	this->hardcoded_button->set_sensitive(true);
	this->adopt_button->set_sensitive(true);
	this->allot_button->set_sensitive(true);
	this->load_button->set_sensitive(true);
	this->save_button->set_sensitive(true);

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

	for (vector<Gtk::CheckButton*>::iterator t = this->type_bool.begin();
	     t != this->type_bool.end();
	     t++)
	  (*t)->set_sensitive(true);
	for (vector<Gtk::LabelSpinButton*>::iterator
	     t = this->type_unsigned.begin();
	     t != this->type_unsigned.end();
	     t++)
	  (*t)->set_sensitive(true);
      } else { // if !(::game_status == GAMESTATUS::PARTY_INIT)
	this->hardcoded_button->set_sensitive(false);
	this->adopt_button->set_sensitive(false);
	this->allot_button->set_sensitive(false);
	this->load_button->set_sensitive(false);

	for (vector<Gtk::RadioButton*>::iterator t = this->aitype.begin();
	     t != this->aitype.end();
	     t++)
	  (*t)->set_sensitive(false);

	for (vector<Gtk::CheckButton*>::iterator t = this->type_bool.begin();
	     t != this->type_bool.end();
	     t++)
	  (*t)->set_sensitive(false);
	for (vector<Gtk::LabelSpinButton*>::iterator
	     t = this->type_unsigned.begin();
	     t != this->type_unsigned.end();
	     t++)
	  (*t)->set_sensitive(false);
      } // if !(::game_status == GAMESTATUS::PARTY_INIT) 

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_UPDATE,
		      "Players::AiConfigs::AiConfig::sensitivity_update()");
    } // void Players::AiConfigs::AiConfig::sensitivity_update()

  /**
   **
   ** update all widgets
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   **/
  void
    Players::AiConfigs::AiConfig::update()
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_UPDATE,
		    "Players::AiConfigs::AiConfig::update()");

      if (!this->is_realized())
	DEBUG_RETURNING(VOID,
			INFO_GTKMM_AICONFIG && INFO_GTKMM_UPDATE,
			"Players::AiConfigs::AiConfig::update()");

      this->aitype[this->aiconfig().aitype() - AITYPE::AITYPE_FIRST]->set_active(true);

      for (vector<Gtk::CheckButton*>::iterator widget = this->type_bool.begin();
	   widget != this->type_bool.end();
	   widget++)
	(*widget)->set_active(this->aiconfig().value(*static_cast<Aiconfig::TypeBool*>((*widget)->get_data("type"))));
      for (vector<Gtk::LabelSpinButton*>::iterator widget
	   = this->type_unsigned.begin();
	   widget != this->type_unsigned.end();
	   widget++) {
	Aiconfig::TypeUnsigned type
	  = *static_cast<Aiconfig::TypeUnsigned*>((*widget)->get_data("type"));
	(*widget)->set_range(this->aiconfig().min(type),
			     this->aiconfig().max(type));
	(*widget)->set_value(this->aiconfig().value(type));
      } // for (widget \in this->type_unsigned)

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_UPDATE,
		      "Players::AiConfigs::AiConfig::update()");
    } // void Players::AiConfigs::AiConfig::update()

  /**
   **
   ** update the name
   **
   ** @param	-
   **
   ** @return	-
   **
   ** @version	0.5.4
   **
   ** @author	Diether Knof
   **
   ** @todo	block 'Entry::change_signal()'
   **
   **/
  void
    Players::AiConfigs::AiConfig::name_update()
    {
      DEBUG_CALLING(INFO_GTKMM_AICONFIG && INFO_GTKMM_UPDATE,
		    "Players::AiConfigs::AiConfig::name_update()");

      if (!this->is_visible())
	DEBUG_RETURNING(VOID,
			INFO_GTKMM_AICONFIG && INFO_GTKMM_UPDATE,
			"Players::AiConfigs::AiConfig::name_update()");

      this->name_bookmark->set_label(Glib::locale_to_utf8(this->player().name()));
      this->ui->change_translation(*(this->save_file_selector),
				   ::translator("Save aiconfig of %splayer%",
						this->player().name()));

      DEBUG_RETURNING(VOID,
		      INFO_GTKMM_AICONFIG && INFO_GTKMM_UPDATE,
		      "Players::AiConfigs::AiConfig::name_update()");
    } // void Players::AiConfigs::AiConfig::name_update()

} // namespace UI_GTKMM_NS

#endif // #ifdef USE_UI_GTKMM
