/* This file is part of cardwords
   (c) 1999 2000 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_gtk_actionselection.cc

#include "cardwords_gtk_common_card_cell_styles.hh"
#include "cardwords_gtk_actionselection.hh"
#include "cardwords_gtk_cardcell.hh"
#include "cardwords_gtk_cardtable.hh"
#include "cardwords_gettext.hh"
#include <gdk/gdkkeysyms.h>
#include <gtk--/label.h>
#include <gtk--/togglebutton.h>
#include <strstream>

CardWords::Gtk_ActionSelection::cell::cell () // init with no card;
{
  gtk_card_cell = 0;
  card = old_card = 0;
}

CardWords::Gtk_ActionSelection::cell::~cell() // delete the card cell if != 0
{
  delete gtk_card_cell;
}

void
CardWords::Gtk_ActionSelection::cell::set(CardWords::Hand::const_iterator iter)
  // set to this card
{
  assert (gtk_card_cell != 0);
  old_card = 0;
  card = *iter;
  gtk_card_cell->set_card(card);
}
void
CardWords::Gtk_ActionSelection::cell::set(CardWords::Card * t)
{
  assert (gtk_card_cell != 0);
  if (t == 0) {
    old_card = card;
  }
  else {
    old_card = 0;
  }
  card = t;
  gtk_card_cell->set_card(card);
}


int
CardWords::Gtk_ActionSelection::key_pressed (GdkEventKey *kevent)
{
  int return_value;
  
  switch(kevent->keyval) {
  case GDK_BackSpace:
  case GDK_Delete:
    return_value = take_key_strike('H' - 64);
    break;
  case GDK_Escape:
    return_value = take_key_strike(27);
    break;
  case GDK_Return:
  case GDK_KP_Enter:
  case GDK_ISO_Enter:
  case GDK_3270_Enter:
    return_value = take_key_strike(13);
    break;
  default:
    if (kevent->length > 0) {
      return_value = take_key_strike(*(kevent->string));
    }
    else {
      return false;
    }
  }
  update();
  if (return_value == 0) {
    return true;
  }
  if (return_value == -1) {
    // Beep? I think it should not.
    return false;
  }
  // return value 1
  action_selection_activated();
  return true;
}

CardWords::Gtk_ActionSelection::
Gtk_ActionSelection(CardWords::Hand *hand,
                    // The hand from where to get the cards. The
                    // hand will be modified, but will be restored
                    // when take_key_strike returns 1 or
                    // when reset() is called.
                    CardWords::Gtk_CardTable * gtk_card_table
                    // With this
                    // pointer, invalid geometric moves will be
                    // detected.
                    )
  :
  CardWords::ActionSelection(hand,

                             gtk_card_table->get_card_table(),

                             gtk_card_table->uses_digits_for_the_columns(),

                             gtk_card_table
                             ->do_column_indices_grow_rightwards(),

                             gtk_card_table->do_row_indices_grow_upwards()
                             ),
    
  currently_updating(false),

  // We currently do not need so many cells, because the cards already on the
  // board are not displayed in the action selection area. Was:
  // cells(cardwords_max(gtk_card_table->get_card_table()->get_width(),
  //                     gtk_card_table->get_card_table()->get_height()))
  cells(hand->total_places())

{
  this->gtk_card_table = gtk_card_table;
  this->styles = gtk_card_table->get_styles();

  set_homogeneous(false);
  set_spacing(0);

  // First add a label to display the starting position:
  tablelocation_label = new Gtk::Label("{A1}");
  tablelocation_label->set_usize(styles->get_cell_width() * 2,
                                 styles->get_cell_height());
  tablelocation_label->set_style(*styles->get_card_face_value_style());
  pack_start(*tablelocation_label, false, false);
  tablelocation_label->show();
  
  size_t index;
  for (index = 0; index < cells.size(); ++index) {
    cells[index].gtk_card_cell =
      new CardWords::Gtk_CardCell (styles, size_t(-1));
    //                       The coordinate ^ doesn't matter
    pack_start(*cells[index].gtk_card_cell, false, false);
    cells[index].gtk_card_cell->show();
    cells[index].gtk_card_cell->clicked_signal.
      connect(SigC::slot(this,
                   &CardWords::Gtk_ActionSelection::received_click_on_card));
  }

  
  ok_button = new Gtk::Button(gettext("OK"));
  /*  vertikal_button = new Gtk::RadioButton(0, gettext("Vertical"));
  GSList * group = 0;
  group = vertikal_button->group();
  horizontal_button = new Gtk::RadioButton(vertikal_button);//->group(),
  horizontal_button->add_label(gettext("Horizontal"));
  */
  horizontal_vertikal_button = new Gtk::ToggleButton();
  
  pack_start(*horizontal_vertikal_button, false, false);
  //  pack_start(horizontal_button, false, false);
  pack_start(*ok_button, false, false);

  horizontal_vertikal_button->unset_flags(GTK_CAN_FOCUS); // it seems to
  //                         react on return and space when it has the focus.
  horizontal_vertikal_button->show();
  // horizontal_button->show();

  ok_button->unset_flags(GTK_CAN_FOCUS); // same as above
  ok_button->show();
  ok_button->clicked.connect(this->action_selection_activated.slot());

  horizontal_vertikal_button->set_active(false);

  /* // Can anybody tell me why this does not work?
  GdkBitmap * mask = 0;
  GdkPixmap * pixmap =
    gdk_pixmap_create_from_xpm_d(clientwindow,
                                 &mask,
                                 0,
                                 cardwords_gtk_horizontal_xpm);
  
  horizontal_pixmap = new Gtk::Pixmap(pixmap, mask);

  mask = 0;
  pixmap =
    gdk_pixmap_create_from_xpm_d(clientwindow,
                                 &mask,
                                 0,
                                 cardwords_gtk_vertikal_xpm);
  vertikal_pixmap = new Gtk::Pixmap(pixmap, mask);
  
  horizontal_vertikal_button->add(horizontal_pixmap);
  */
  horizontal_vertikal_label = new Gtk::Label("horizantal");
  
  
  horizontal_vertikal_button->add(*horizontal_vertikal_label);
  horizontal_vertikal_label->show();
  
  horizontal_vertikal_button->toggled.
    connect(SigC::slot(this,
                 &CardWords::Gtk_ActionSelection::toggle_button_clicked));
  
  update();
}

void
CardWords::Gtk_ActionSelection::toggle_button_clicked(void)
{
  if (currently_updating) {
    // Ignore this toggle, it is initiated by the update() method and the
    // data is already set right.
    return;
  }
  if (horizontal_vertikal_button->get_active() == true) {
    change_direction(vertikal);
  }
  else {
    change_direction(horizontal);
  }
  update();
}

void
CardWords::Gtk_ActionSelection::update(void)
{
  assert(currently_updating != true); // I think this can't happen
  
  // read the contents of the underlying CardWords::ActionSelection object and
  // display it:
  currently_updating = true;
  {
    ostrstream location;
    print_user_start_coordinates(location);
    location << ends;
    location.freeze(true);
    tablelocation_label->set(location.str());
    location.freeze(false);
  }
  
  CardWords::CardSelection sel;
  if (get_move() == 0) {
    gtk_card_table->unpre();
  }
  else {
    gtk_card_table->pre(*get_move());
  }
  
  if (get_move() != 0) {
    sel = *get_move();
  }
  else if (get_trade() != 0) {
    sel = *get_trade();
  }
  size_t index;
  CardWords::Card * card_at_index;
  for ((index = 0);
       index < sel.size();
       (++index)) {
    card_at_index = get_card(index);
    if (card_at_index != cells[index].card) {
      cells[index].set(get_card(index));
    }
  }
  for (index = sel.size(); index < cells.size(); ++index) {
    if (cells[index].card != 0) {
      cells[index].set(static_cast<CardWords::Card *>(0));
    }
  }
  if (get_move_direction() == 0) {
    horizontal_vertikal_label->set("    ");
  }
  else if (*get_move_direction() == horizontal) {
    horizontal_vertikal_label->set("horizontal");
    horizontal_vertikal_button->set_active(false);
  }
  else {
    horizontal_vertikal_label->set("vertikal");
    horizontal_vertikal_button->set_active(true);
  }
  currently_updating = false;
}

void
CardWords::Gtk_ActionSelection::
received_click_on_card(const CardWords::Gtk_CardCell * cardcell)
{
  size_t index;
  // Search that card:
  for (index = 0; index < cells.size(); ++index) {
    if (cells[index].gtk_card_cell == cardcell) {
      if (cells[index].card != 0) {
        card_clicked(cells[index].card);
      }
      return;
    }
  }
}

