/* 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_gtk_cardlist.cc

#include "cardwords_gtk_cardlist.hh"
#include "cardwords_gettext.hh"
#include "cardwords_carddescription.hh"
#include <gtk--/clist.h>
#include <gtk--/style.h>
#include <vector>

// CardWords_Gtk_CardList is a window displaying the number of occurrences
// of cards.


CardWords_Gtk_CardList::
CardWords_Gtk_CardList(const CardWords_CardOccurrenceMap *occ_map,
                       bool static_map = false)
{
  size_t min_width = 0;
  size_t act_width;
  
  list = new Gtk::CList(3);
  list->set_selection_mode(GTK_SELECTION_SINGLE);
  //  list->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  
  list->column_titles_show();

  list->set_column_title(0, gettext("Character"));
  list->set_column_justification(0, GTK_JUSTIFY_CENTER);
  act_width = gdk_string_width(get_style()->get_font(),
                               gettext("Character"));
  list->set_column_width(0, act_width);
  min_width += act_width;

  list->set_column_title(1, gettext("Points"));
  list->set_column_justification(1, GTK_JUSTIFY_RIGHT);
  act_width = gdk_string_width(get_style()->get_font(),
                               gettext("Points"));
  list->set_column_width(1, act_width);
  min_width += act_width;

  string number_description =
    (static_map
     ? gettext("Total cards")
     : gettext("Remaining cards"));
  
  list->set_column_title(2, number_description);
  list->set_column_justification(2, GTK_JUSTIFY_RIGHT);
  act_width = gdk_string_width(get_style()->get_font(),
                               number_description.c_str());
  list->set_column_width(2, act_width);
  min_width += act_width;

  
  CardWords_CardOccurrenceMap::const_iterator iter;
  size_t row_number;
  map_value_type values;
  CardWords_CardDescription desc;
  
  for ((iter = occ_map->begin()),(row_number = 0);
       iter != occ_map->end();
       (++iter),(++row_number)) {
    desc = (*iter).first;
    values.number_of_occurrences = (*iter).second;
    values.position_in_clist = row_number;
    card_map.insert(pair<CardWords_CardDescription, map_value_type>
                    (desc, values));

    ostrstream character_stream;
    character_stream << desc.get_faceValue() << ends;

    ostrstream points_stream;
    points_stream << desc.get_points() << ends;

    ostrstream occurrences_stream;
    occurrences_stream << values.number_of_occurrences << ends;

    character_stream.freeze(true);
    points_stream.freeze(true);
    occurrences_stream.freeze(true);

    vector<string> columns(3);
    columns[0] = character_stream.str();
    columns[1] = points_stream.str();
    columns[2] = occurrences_stream.str();
    
    list->append(columns);

    character_stream.freeze(false);
    points_stream.freeze(false);
    occurrences_stream.freeze(false);
  }

  set_usize(min_width + 3 * 10,
            (list->get_style()->get_font().gdkobj()->ascent
             + list->get_style()->get_font().gdkobj()->descent
             + 3) * (card_map.size() + 3)
            );

  add(*list);
  list->show();

#ifdef DEBUG
  this->static_map = static_map;
#endif

  set_title(static_map
            ? gettext("All cards in the game")
            : gettext("Cards possibly still in the pile"));
}

  
CardWords_Gtk_CardList::~CardWords_Gtk_CardList()
{
  list->hide();
  remove(/*list*/);

  delete(list);
  list = 0;
}

void
CardWords_Gtk_CardList::
remaining_card_diminished(const CardWords_CardDescription &desc)
{
#ifdef DEBUG
  {
    assert(static_map == false); // A static map should not change.
  }
#endif
  // This did not work: parse error before ,
  // map < class CardWords_CardDescription , map_value_type >::iterator pos;
  clist_map_type::iterator pos;
  
  pos = card_map.find(desc);

  assert(pos != card_map.end()); // Would be a serious bug if this happened.

  map_value_type & values = (*pos).second;

  assert(values.number_of_occurrences > 0); // There has to have been some
  //                                           card until now.

  --values.number_of_occurrences;

  ostrstream occurrence_stream;
  occurrence_stream << values.number_of_occurrences << ends;

  occurrence_stream.freeze(true);
  list->set_text(values.position_in_clist, 2, occurrence_stream.str());
  occurrence_stream.freeze(false);
}

void
CardWords_Gtk_CardList::
remaining_card_increased(const CardWords_CardDescription &desc)
{
#ifdef DEBUG
  {
    assert(static_map == false); // A static map should not change.
  }
#endif
  // This did not work: parse error before ,
  // map < class CardWords_CardDescription , map_value_type >::iterator pos;
  clist_map_type::iterator pos;
  
  pos = card_map.find(desc);

  assert(pos != card_map.end()); // Would be a serious bug if this happened.

  map_value_type & values = (*pos).second;

  ++values.number_of_occurrences;

  ostrstream occurrence_stream;
  occurrence_stream << values.number_of_occurrences << ends;

  occurrence_stream.freeze(true);
  list->set_text(values.position_in_clist, 2, occurrence_stream.str());
  occurrence_stream.freeze(false);
}

// override delete: hide instead of destroy.
gint
CardWords_Gtk_CardList::delete_event_impl(GdkEventAny*)
{
  hide();
  return true;
}

// overide show: It raises the window if it already there but hidden.
void
CardWords_Gtk_CardList::show_impl(void)
{
  // first show the window:
  Gtk::Window::show_impl();

  // then raise it:
  // The window may already be open but hidden behind some other windows on
  // the screen. This should bring it to the top again.
  gdk_window_show(this->get_window());
  gdk_window_raise(this->get_window());
}  
