/* This file is part of cardwords
   (c) 1999 Tobias Peters
   see file COPYING for the copyright terms.
   
   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 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
*/

// cardwords_gtkclient.hh

#ifndef CARDWORDS_GTKCLIENT_HH
#define CARDWORDS_GTKCLIENT_HH

#include "cardwords_commclient.hh"
#include "cardwords_gtk_cardtable.hh"
#include "cardwords_gtk_playerlist.hh"
#include "cardwords_gtk_actionselection.hh"
#include "cardwords_gtk_handdisplay.hh"
#include "cardwords_gtk_pileinfo.hh"
#include "cardwords_gtk_addword.hh"
#include "cardwords_gtk_optionsdialog.hh"
#include "cardwords_childprocess.hh"
#include "cardwords_options.hh"
#include "cardwords_gtk_helpwindow.hh"
#include "cardwords_gtk_cardlist.hh"
#include "cardwords_gtk_menu.hh"
// #include "cardwords_gtk_popup.hh"

class CardWords_Gtk_Popup;


class CardWords_GtkClient : public CardWords_CommClient, public Gtk::VBox
{
public:
  CardWords_GtkClient(CardWords_Options *);
  virtual ~CardWords_GtkClient();

  // Functions for registering this object's fd in the gtk main select(2)
  // call:
  virtual void
  register_reading(void);

  virtual void
  register_writing(void);

  virtual void
  deregister_reading(void);

  // If you want to discard all pending messages, use discard_messages() prior
  // to deregister_writing()
  virtual void
  deregister_writing(void);

  // This function is called from the gtk main selection mechanism,
  // and call read_now(), send_now() method of the client_object
  static void socket_read_possible (gpointer client_object,
                                    gint fd,
                                    GdkInputCondition condition);
  static void socket_write_possible (gpointer client_object,
                                     gint fd,
                                     GdkInputCondition condition);
  // client_object is the registered instance.
  // condition is GDK_INPUT_READ or GDK_INPUT_WRITE.


  // When the state of the connection, the game or other things are changed,
  // this function is called. It should display the changes for the user or
  // do other neat things.
  virtual void
  state_changed(State_Change);

  // Test if the client is compatible with these charset, cardset, table
  // and bonus definitions:
  virtual bool
  test_client_compatible_with_server_settings();

  // The virtual method error() will be called with an Error_Number
  // parameter and should inform the user about that error.
  // The error() method should call disconnect() or
  // CardWords_CommClient::error() before returning to disconnect
  // from the server.
  virtual void
  error (CardWords_CommClient::Error_Number);

  virtual void
  disconnect(void);

  int // to be called from static_remove_button_box_and_connect:
  remove_button_box_and_connect(void);
  
protected:
  // When the player draws a new card or cards from other players are moved
  // to the board, the client knows what cards are still remaining.
  // This method is a hint for clients to update displays showing
  // the remaining possible cards:
  virtual void
  remaining_card_diminished(const CardWords_CardDescription &);
  // When the player trades cards, they get back to the pile:
  virtual void
  remaining_card_increased(const CardWords_CardDescription &);

private:
  void
  remove_card_from_actionsel(CardWords_Card *);
  void
  move_card_from_hand_to_actionsel(CardWords_Card *);
  int
  key_pressed (GdkEventKey *);
  void
  action_is_chosen(void);
  void
  new_start_location_chosen_through_mouse_click(CardWords_CardTableLocation);

  gint
  all_cards_list_delete_event_callback(GdkEventAny *);
  gint
  remaining_cards_list_delete_event_callback(GdkEventAny *);
  
  void
  start_local_button_callback(void);
  void
  connect_remote_button_callback(void);
  void
  save_options_button_callback(void);

  // read all options relevant for this (gtk) client
  void
  read_client_options(void);

  // These tags are received from the gtk fd registering mechanism and needed
  // for deregistering:
  gint gdk_socket_read_tag;
  gint gdk_socket_write_tag;

  Gtk::HBox * table_and_info_box;
  Gtk::VBox * table_box;
  Gtk::VBox * info_box;
  
  CardWords_Gtk_CardTable      * gtk_table;
  CardWords_Gtk_CardTableInfo  * gtk_tableinfo;
  CardWords_Gtk_PlayerList * gtk_playerlist;
  CardWords_Gtk_PileInfo    * gtk_pileinfo;

  CardWords_Gtk_AddWord    * gtk_addword; // Question to add a word
  
  CardWords_Gtk_ActionSelection * actionsel; 

  CardWords_Gtk_HandDisplay * hand_display;

  bool use_digits_for_the_columns;
  // and chars for the rows, otherwise the other way
  // round
                          
  bool column_indices_grow_rightwards;
  // if true, the rightmost column has the greatest
  // index
                          
  bool row_indices_grow_upwards;

  bool allow_action_selection; // Allow only if it is my go.

  CardWords_ChildProcess * server;

  CardWords_Gtk_OptionsDialog * options_dialog;

  unsigned cell_height, cell_width;

  CardWords_Gtk_HelpWindow * help_window;

  CardWords_Gtk_CardList   * all_cards_list;
  CardWords_Gtk_CardList   * remaining_cards_list;
  CardWords_Gtk_Popup      * popup;

  CardWords_Gtk_MenuBar * menu_bar;

  CardWords_Options * options;

  Gtk::HBox * button_box;
  Gtk::Button * start_local_button;
  Gtk::Button * save_options_button;
  Gtk::Button * connect_remote_button;
  Gtk::Button * exit_button;
  
  size_t max_table_dimensions[2];

  bool user_wants_connect; // flag set by clicks on start_local_button and
  //                          connect_remote_button.
};
#endif
