/**********************************************************************
 *
 *   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_points.h"
#include "gtk_gui.h"
#include "table.h"
#include "card.h"

#include "../../party/party.h"
#include "../../game/gamepointstable.h"
#include "../../misc/language.h"
#include "../../utils/string.h"

namespace GTK_DOKO {
#include <gtk/gtkdialog.h>
#include <gtk/gtkclist.h>
#include <gtk/gtkvbox.h>
#include <gtk/gtkhbox.h>

  /*****************************************************************************
   *
   * PartyPoints::PartyPoints(class Table* table_a)
   *
   * Parameters:	table_a - pointer to the table
   *
   * Result:	none
   * 
   * Version:	0.3.7
   *
   * Description:	Constructor
   *
   ****************************************************************************/
  PartyPoints::PartyPoints(class Table* table_a) :
    TableDialog(table_a, "Party points"), // the base class
  scrollbar(gtk_vscrollbar_new(NULL)), // the scrollbar for the list
  pointlist(gtk_clist_new(::party.playerno() + 1)), // the list with the points
  sum(gtk_clist_new(::party.playerno() + 1)), // the list with the points
  game_summary()
  {
    DEBUG_CALLING(INFO_GTK_PARTY_POINTS && INFO_GTK_INIT,
		  "PartyPoints::PartyPoints()");

    GtkWidget* container = gtk_hbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window())->vbox),
		      container);

    // the list
    GtkWidget* box_list_description = gtk_hbox_new(FALSE, 0);
    GtkWidget* box_lists_scrollbar = gtk_hbox_new(FALSE, 0);
    GtkWidget* box_lists = gtk_vbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(container),
		       box_list_description,
		       FALSE, TRUE, 0);
    gtk_container_add(GTK_CONTAINER(box_list_description),
		      box_lists_scrollbar);
    gtk_box_pack_start(GTK_BOX(box_lists_scrollbar), box_lists,
		       TRUE, TRUE, 0);
    gtk_box_pack_end(GTK_BOX(box_lists_scrollbar), scrollbar,
		     FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(box_lists), pointlist,
		       TRUE, TRUE, 0);
    gtk_box_pack_end(GTK_BOX(box_lists), sum,
		     FALSE, FALSE, 0);

    // the description
    gtk_box_pack_end(GTK_BOX(container),
		     this->game_summary.widget(),
		     TRUE, TRUE, 0);

    // the button
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window())->action_area),
		      button_close);


    DEBUG_RETURNING(VOID,
		    INFO_GTK_PARTY_POINTS && INFO_GTK_INIT,
		    "PartyPoints::PartyPoints()");
  } // PartyPoints::PartyPoints(class Table* table_a)

  /*****************************************************************************
   *
   * void PartyPoints::init()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.3.7
   *
   * Description:	inits the 'party points' window
   *
   ****************************************************************************/
  void
    PartyPoints::init()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_POINTS && INFO_GTK_INIT,
		    "PartyPoints::init()");

      this->TableDialog::init();
      this->game_summary.init();
      this->names_update();

      gtk_widget_hide(this->game_summary.widget());

      { // some setttings of the list
	gtk_clist_column_titles_show(GTK_CLIST(pointlist));
	for (unsigned c = 0; c < ::party.playerno() + 1; c++) {
	  gtk_clist_set_column_resizeable(GTK_CLIST(pointlist), c, FALSE);
	  gtk_clist_set_column_justification(GTK_CLIST(pointlist), c,
					     GTK_JUSTIFY_CENTER);
	  gtk_clist_set_column_resizeable(GTK_CLIST(sum), c, FALSE);
	  gtk_clist_set_column_justification(GTK_CLIST(sum), c,
					     GTK_JUSTIFY_CENTER);
	}

	gtk_clist_set_vadjustment(GTK_CLIST(this->pointlist),
				  gtk_range_get_adjustment(GTK_RANGE(scrollbar)));
      } // some settings of the list

      // set minimum size for the list
      gtk_widget_set_usize(this->pointlist,
			   -1,
			   this->gui().cards().height()
			   + this->gui().cards().width());

      { // add the sum row and make the background gray
	gchar** row = new gchar*[::party.playerno() + 1];
	for (unsigned c = 0; c < ::party.playerno() + 1; c++)
	  row[c] = "0";
	gtk_clist_append(GTK_CLIST(sum), row);

	GdkColor gray;
	gdk_color_parse("gray", &gray);
	gtk_clist_set_background(GTK_CLIST(sum), 0, &gray);
      } // add the sum row and make the background gray

      // select and unselect event
      gtk_signal_connect(GTK_OBJECT(pointlist), "select_row",
			 GTK_SIGNAL_FUNC(PartyPoints::select_row_event),
			 gpointer(this));
      gtk_signal_connect(GTK_OBJECT(pointlist), "unselect_row",
			 GTK_SIGNAL_FUNC(PartyPoints::unselect_row_event),
			 gpointer(this));


      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_POINTS && INFO_GTK_INIT,
		      "PartyPoints::init()");
    } // void PartyPoints::init()

  /*****************************************************************************
   *
   * void PartyPoints::party_start()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.3.7
   *
   * Description:	the party is closeed
   *		write the remaining points
   *
   ****************************************************************************/
  void
    PartyPoints::party_start()
    {
      DEBUG_CALLING(INFO_GTK_PLAYFIELD && INFO_GTK_GAMEPLAY,
		    "PartyPoints::party_start()");

      GamePointsTable const& gamepointstable
	= static_cast<Party const&>(party).gamepointstable();

      // update the sum

      gtk_clist_freeze(GTK_CLIST(sum));
      for (unsigned p = 0; p < ::party.playerno(); p++)
	gtk_clist_set_text(GTK_CLIST(sum), 0, p, "0");

      // the remaining points
      gtk_clist_set_text(GTK_CLIST(sum), 0, ::party.playerno(),
			 DK::Utils::String::to_string(gamepointstable.remainingpoints()).c_str());

      gtk_clist_thaw(GTK_CLIST(sum));

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYFIELD && INFO_GTK_GAMEPLAY,
		      "PartyPoints::party_start()");
    } // void PartyPoints::party_start()

  /*****************************************************************************
   *
   * void PartyPoints::game_finish()
   *
   * Parameters:	none
   *
   * Result:	none
   *
   * Version:	0.3.7
   *
   * Description:	adds the line for this game
   *
   ****************************************************************************/
  void
    PartyPoints::game_finish()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_POINTS && INFO_GTK_GAMEPLAY,
		    "PartyPoints::game_finish()");

      // add a row with the new points to the table
      if (::game_status & GAMESTATUS::GAME) {

	unsigned p; // counter for the columns

	GamePointsTable const& gamepointstable
	  = static_cast<Party const&>(::party).gamepointstable();
	GamePoints const& gamepoints
	  = gamepointstable.gamepoints(gamepointstable.gameno() - 1);

	const char** row = (const char**) new char*[party.playerno() + 1];


	for (p = 0; p < ::party.playerno(); p++) {
	  if (gamepoints.team(p) == gamepoints.winnerteam())
	    row[p] = DK::Utils::String::to_string(gamepoints.points()).c_str();
	  else
	    row[p] = "-";

	} // for (p < playerno())

	row[party.playerno()] = DK::Utils::String::to_string(gamepoints.points()).c_str();

	int number // number of the last row
	  = gtk_clist_append(GTK_CLIST(pointlist), (gchar**)row);
	delete[] (row);

	gtk_clist_moveto(GTK_CLIST(pointlist), 1, number, 0, 1);


	// update the sum

	gtk_clist_freeze(GTK_CLIST(sum));
	for (p = 0; p < ::party.playerno(); p++) {
	  gtk_clist_set_text(GTK_CLIST(sum), 0, p,
			     DK::Utils::String::to_string(gamepointstable.points(p)).c_str());
	} // for (p < playerno())

	// write the remaining points
	gtk_clist_set_text(GTK_CLIST(sum), 0, ::party.playerno(),
			   DK::Utils::String::to_string(gamepointstable.remainingpoints()).c_str());

	gtk_clist_thaw(GTK_CLIST(sum));
      } // if (::game_status == GAMESTATUS & GAME)

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_POINTS && INFO_GTK_GAMEPLAY,
		      "PartyPoints::game_finish()");
    } // void PartyPoints::game_finish()

  /*****************************************************************************
   *
   * void PartyPoints::party_close()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.3.7
   *
   * Description:	the party is closeed
   *		clear the list
   *
   ****************************************************************************/
  void
    PartyPoints::party_close()
    {
      DEBUG_CALLING(INFO_GTK_PLAYFIELD && INFO_GTK_GAMEPLAY,
		    "PartyPoints::party_close()");

      gtk_clist_clear(GTK_CLIST(pointlist));

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PLAYFIELD && INFO_GTK_GAMEPLAY,
		      "PartyPoints::party_close()");
    } // void PartyPoints::party_close()

  /*****************************************************************************
   *
   * void PartyPoints::names_update()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.3.7
   *
   * Description:	updates the names of the players
   *		and resizes the columns
   *
   ****************************************************************************/
  void
    PartyPoints::names_update()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_POINTS && INFO_GTK_UPDATE,
		    "PartyPoints::names_update()");

      this->game_summary.language_update();

      int width = 0;

      unsigned p;

      for (p = 0; p < ::party.playerno(); p++) {
	gtk_clist_set_column_title(GTK_CLIST(pointlist), p,
				   (" " + ::party.player(p).name() + " ").c_str());
	width = max(width,
		    gtk_clist_optimal_column_width(GTK_CLIST(pointlist), p));
      } // for (p < playerno())

      for (p = 0; p < ::party.playerno(); p++) {
	gtk_clist_set_column_width(GTK_CLIST(pointlist), p, width);
	gtk_clist_set_column_width(GTK_CLIST(sum), p, width);
      } // for (p < playerno())

      width =  gtk_clist_optimal_column_width(GTK_CLIST(pointlist),
					      ::party.playerno());

      gtk_clist_set_column_width(GTK_CLIST(pointlist), ::party.playerno(),
				 width);
      gtk_clist_set_column_width(GTK_CLIST(sum), ::party.playerno(),
				 width);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_POINTS && INFO_GTK_UPDATE,
		      "PartyPoints::names_update()");
    } // void PartyPoints::names_update()

  /*****************************************************************************
   *
   * void PartyPoints::language_update()
   *
   * Parameters:	none
   *
   * Result:	none
   * 
   * Version:	0.3.7
   *
   * Description:	updates the language
   *
   ****************************************************************************/
  void
    PartyPoints::language_update()
    {
      DEBUG_CALLING(INFO_GTK_PARTY_POINTS && INFO_GTK_UPDATE,
		    "PartyPoints::language_update()");

      this->names_update();
      this->TableDialog::language_update();
      this->game_summary.language_update();

      // the list
      gtk_clist_set_column_title(GTK_CLIST(pointlist), ::party.playerno(),
				 language("game").c_str());

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_POINTS && INFO_GTK_UPDATE,
		      "PartyPoints::language_update()");
    } // void PartyPoints::language_update()

  /*****************************************************************************
   *
   * static void PartyPoints::select_row_event(GtkWidget*, gint row, gint,
   *					     GdkEvent*,
   *					     gpointer party_points)
   *
   * Parameters:	row - the selected row
   *		party_points - PartyPoints of the event
   *
   * Result:	none
   *
   * Version:	0.3.7
   *
   * Description:	calls party_points->game_select()
   *
   ****************************************************************************/
  void
    PartyPoints::select_row_event(GtkWidget*, gint row, gint, GdkEvent*,
				  gpointer party_points)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_POINTS && INFO_GTK_EVENT,
		    "PartyPoints::select_row_event()");

      DEBUG_ASSERTION((party_points != NULL),
		      "PartyPoints::select_row_event():\n"
		      "  'party_points' == NULL");

      ((PartyPoints*)party_points)->game_select(row);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_POINTS && INFO_GTK_EVENT,
		      "PartyPoints::select_row_event()");
    } // static void PartyPoints::select_row_event(GtkWidget*, row, gint, GdkEvent*, gpointer party_points)

  /*****************************************************************************
   *
   * static void PartyPoints::unselect_row_event(GtkWidget*, gint row, gint,
   *					       GdkEvent*,
   *					       gpointer party_points)
   *
   * Parameters:	row - the unselected row
   *		party_points - PartyPoints of the event
   *
   * Result:	none
   *
   * Version:	0.3.7
   *
   * Description:	calls party_points->game_unselect()
   *
   ****************************************************************************/
  void
    PartyPoints::unselect_row_event(GtkWidget*, gint row, gint, GdkEvent*,
				    gpointer party_points)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_POINTS && INFO_GTK_EVENT,
		    "PartyPoints::unselect_row_event()");

      DEBUG_ASSERTION((party_points != NULL),
		      "PartyPoints::unselect_row_event():\n"
		      "  'party_points' == NULL");

      ((PartyPoints*)party_points)->game_unselect(row);

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_POINTS && INFO_GTK_EVENT,
		      "PartyPoints::unselect_row_event()");
    } // static void PartyPoints::unselect_row_event(GtkWidget*, row, gint, GdkEvent*, gpointer party_points)

  /*****************************************************************************
   *
   * void PartyPoints::game_select(unsigned const gameno)
   *
   * Parameters:	gameno - the selected game
   *
   * Result:	the gamenumber
   * 
   * Version:	0.3.7
   *
   * Description:	sets the gamenumber
   *
   ****************************************************************************/
  void
    PartyPoints::game_select(unsigned const gameno)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_POINTS && INFO_GTK_EVENT,
		    "PartyPoints::game_select()");

      DEBUG_ASSERTION((gameno < (static_cast<Party const&>(::party)).gamepointstable().gameno()),
		      "GTK_DOKO::PartyPoints::game_select(gameno):\n"
		      "  'gameno_a' not valid");

      this->game_summary.gameno_set(gameno);
      gtk_widget_show(this->game_summary.widget());

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_POINTS && INFO_GTK_EVENT,
		      "PartyPoints::game_select()");
    } // void PartyPoints::game_select(unsigned const gameno)

  /*****************************************************************************
   *
   * void PartyPoints::game_unselect(unsigned const gameno)
   *
   * Parameters:	gameno - the unselected game
   *
   * Result:	the gamenumber
   * 
   * Version:	0.3.7
   *
   * Description:	sets the gamenumber
   *
   ****************************************************************************/
  void
    PartyPoints::game_unselect(unsigned const gameno)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_POINTS && INFO_GTK_EVENT,
		    "PartyPoints::game_unselect()");

      gtk_widget_hide(this->game_summary.widget());

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_POINTS && INFO_GTK_EVENT,
		      "PartyPoints::game_unselect()");
    } // void PartyPoints::game_unselect(unsigned const gameno)


  /*****************************************************************************
   *
   * void PartyPoints::key(GdkEventKey* key)
   *
   * Parameters:	key - the pressed key
   *
   * Result:	none
   * 
   * Version:	0.3.7
   *
   * Description:	manages the pressed keys for the PartyPoints window
   *
   ****************************************************************************/
  void
    PartyPoints::key(GdkEventKey* key)
    {
      DEBUG_CALLING(INFO_GTK_PARTY_POINTS && INFO_GTK_KEY,
		    "PartyPoints::key()");

#include <gdk/gdkkeysyms.h>

      switch (key->keyval) {
	//  case GDK_space: // the space selects a row in the clist
      case GDK_Return:
      case GDK_Escape:
	// close this window
	this->close();
	break;

      default: // pass the key to the table
	this->TableDialog::table().key(key);
	break;
      } // switch (key->keyval)

      DEBUG_RETURNING(VOID,
		      INFO_GTK_PARTY_POINTS && INFO_GTK_KEY,
		      "PartyPoints::key()");
    } // void PartyPoints::key(GdkKeyEvent);

}
#endif
