/** -*- Mode: C++; tab-width: 4 -*-
 * vim: sw=4 ts=4:
 *
 * Gnome Apt filter manipulation bar
 *
 * 	(C) 1998 Havoc Pennington <hp@pobox.com>
 * 	    2003, 2004 Filip Van Raemdonck <mechanix@debian.org>
 *
 * 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
 *
 * 	$Id$
 *
 **/

using namespace std;

#include "filterbar.h"
#include "gtkexpander.h"
#include "search.h"

GAptFilterBar::GAptFilterBar(Filter* filter)
  : filter_(filter), changing_state_(false)
{
  g_assert(filter_);

  filter_->add_view(this);

	bar_ = gtk_expander_new (_("Filter Listed Packages"), _("Filter Listed Packages"), 0);

	GtkWidget* hbox = gtk_hbox_new (FALSE, 0);
	gtk_container_add (GTK_CONTAINER (bar_), hbox);

	GtkWidget* tbl = gtk_table_new (2, 2, FALSE);
	gtk_container_set_border_width (GTK_CONTAINER (tbl), GAPT_PAD_BIG);
	gtk_table_set_row_spacings (GTK_TABLE (tbl), 0);
	gtk_table_set_col_spacings (GTK_TABLE (tbl), GAPT_PAD_BIG);
	gtk_box_pack_start (GTK_BOX (hbox), tbl, FALSE, FALSE, 0);

	GtkWidget* lbl = gtk_label_new (_("Status Filter"));
	gtk_label_set_justify (GTK_LABEL (lbl), GTK_JUSTIFY_LEFT);
	gtk_table_attach (GTK_TABLE (tbl), lbl, 0, 2, 0, 1, GTK_FILL, (GtkAttachOptions) 0, 0, 0);
	gtk_misc_set_alignment (GTK_MISC (lbl), 0, 0.5);

	GtkWidget* vbox = gtk_vbox_new (FALSE, 0);
	gtk_table_attach (GTK_TABLE (tbl), vbox, 1, 2, 1, 2, GTK_FILL, (GtkAttachOptions) 0, 0, 0);

/*	GtkWidget* item = gtk_check_button_new_with_label (_("All statuses"));
	gtk_box_pack_start (GTK_BOX (vbox), item, TRUE, TRUE, 0);
	g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (::status_clear), this);

  GtkWidget* item       = gtk_menu_item_new_with_label(_("Clear all"));
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
	g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (::all_clear), this);

  item                  = gtk_menu_item_new_with_label(_("Reverse all"));
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
	g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (::all_reverse), this);

  item = gtk_menu_item_new_with_label(_("Reverse"));
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
	g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (::status_reverse), this);*/

  int i = 0;
	while (i < GAptCache::StatusTypeEnd) {
		GAptCache::PkgStatusType status = static_cast<GAptCache::PkgStatusType> (i);
		const char* s = GAptCache::statusText (status);
		GtkWidget* mi = gtk_check_button_new_with_label (s);
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mi), filter_->get_status_filter (status));

      statuses_[mi] = status;
		gtk_box_pack_start (GTK_BOX (vbox), mi, TRUE, TRUE, 0);
		g_signal_connect (G_OBJECT (mi), "toggled", G_CALLBACK (::status_toggled), this);

      ++i;
    }

	tbl = gtk_table_new (2, 2, FALSE);
	gtk_container_set_border_width (GTK_CONTAINER (tbl), GAPT_PAD_BIG);
	gtk_table_set_row_spacings (GTK_TABLE (tbl), 0);
	gtk_table_set_col_spacings (GTK_TABLE (tbl), GAPT_PAD_BIG);
	gtk_box_pack_start (GTK_BOX (hbox), tbl, FALSE, FALSE, 0);

	lbl = gtk_label_new (_("Priority Filter"));
	gtk_label_set_justify (GTK_LABEL (lbl), GTK_JUSTIFY_LEFT);
	gtk_table_attach (GTK_TABLE (tbl), lbl, 0, 2, 0, 1, GTK_FILL, (GtkAttachOptions) 0, 0, 0);
	gtk_misc_set_alignment (GTK_MISC (lbl), 0, 0.5);

	vbox = gtk_vbox_new (FALSE, 0);
	gtk_table_attach (GTK_TABLE (tbl), vbox, 1, 2, 1, 2, GTK_FILL, (GtkAttachOptions) 0, 0, 0);

/*	item = gtk_menu_item_new_with_label (_("All"));
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
	g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (::priority_clear), this);

  item = gtk_menu_item_new_with_label(_("Reverse"));
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
	g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (::priority_reverse), this);*/

  // don't want to depend on int mapping for this,
  //  since it's outside my control
  pkgCache::State::VerPriority iter_array[] = {
    pkgCache::State::Important,
    pkgCache::State::Required,
    pkgCache::State::Standard,
    pkgCache::State::Optional,
    pkgCache::State::Extra
  };

  // apt-pkg has no static function to convert to string,
  //  plus they wouldn't be capitalized
  // Don't i18n this until apt-pkg is; these aren't really 
  //  translatable anyway
  const char* pri_names[] = {
    "Important",
    "Required",
    "Standard",
    "Optional",
    "Extra"
  };

  i = 0;
  while (i < int(sizeof(iter_array)/sizeof(iter_array[0])))
    {
      pkgCache::State::VerPriority priority = iter_array[i];

      const char* s = pri_names[i];
		GtkWidget* mi = gtk_check_button_new_with_label (s);
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mi), filter_->get_priority_filter (priority));

      priorities_[mi] = priority;
		gtk_box_pack_start (GTK_BOX (vbox), mi, TRUE, TRUE, 0);
		g_signal_connect (G_OBJECT (mi), "toggled", G_CALLBACK (::priority_toggled), this);

      ++i;
    }

	GtkWidget* w = gapt_search_new (gnome_apt_cache_file());
	gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0);
	filter_->set_search_filter (GAPT_SEARCH (w));

	gtk_expander_set_expanded (GTK_EXPANDER (bar_), TRUE);
}

GAptFilterBar::~GAptFilterBar (void) {
	filter_->remove_view (this);
	delete filter_;
}

void
GAptFilterBar::filter_changed()
{
  if (changing_state_) return;

  changing_state_ = true;

	map<GtkWidget*, GAptCache::PkgStatusType>::iterator i = statuses_.begin();
	while (i != statuses_.end()) {
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (i->first),
		      filter_->get_status_filter (i->second));
      ++i;
    }

  map<GtkWidget*,pkgCache::State::VerPriority>::iterator j = priorities_.begin();
	while (j != priorities_.end()) {
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (j->first),
		      filter_->get_priority_filter (j->second));
      ++j;
    }

  changing_state_ = false;
}

void
status_toggled(GtkWidget* w, gpointer data)
{
  GAptFilterBar* fb = static_cast<GAptFilterBar*>(data);
  g_return_if_fail(fb != 0);
  fb->status_toggled(w);
}


void
priority_toggled(GtkWidget* w, gpointer data)
{
  GAptFilterBar* fb = static_cast<GAptFilterBar*>(data);
  g_return_if_fail(fb != 0);
  fb->priority_toggled(w);
}


void
priority_reverse(GtkWidget* w, gpointer data)
{
  GAptFilterBar* fb = static_cast<GAptFilterBar*>(data);
  g_return_if_fail(fb != 0);
  fb->priority_reverse(w);
}

void
priority_clear  (GtkWidget* w, gpointer data)
{
  GAptFilterBar* fb = static_cast<GAptFilterBar*>(data);
  g_return_if_fail(fb != 0);
  fb->priority_clear(w);
}

void
status_reverse  (GtkWidget* w, gpointer data)
{
  GAptFilterBar* fb = static_cast<GAptFilterBar*>(data);
  g_return_if_fail(fb != 0);
  fb->status_reverse(w);
}

void
status_clear    (GtkWidget* w, gpointer data)
{
  GAptFilterBar* fb = static_cast<GAptFilterBar*>(data);
  g_return_if_fail(fb != 0);
  fb->status_clear(w);
}

void
all_reverse     (GtkWidget* w, gpointer data)
{
  GAptFilterBar* fb = static_cast<GAptFilterBar*>(data);
  g_return_if_fail(fb != 0);
  fb->all_reverse(w);
}

void
all_clear       (GtkWidget* w, gpointer data)
{
  GAptFilterBar* fb = static_cast<GAptFilterBar*>(data);
  g_return_if_fail(fb != 0);
  fb->all_clear(w);
}


void
GAptFilterBar::status_toggled(GtkWidget* w)
{
  if (changing_state_) return;

	map<GtkWidget*, GAptCache::PkgStatusType>::const_iterator i = statuses_.find (w);
	g_return_if_fail (i != statuses_.end());
	GAptCache::PkgStatusType status = i->second;

  changing_state_ = true;
	filter_->set_status_filter (status, GTK_TOGGLE_BUTTON (w)->active);
  changing_state_ = false;
}


void
GAptFilterBar::priority_toggled(GtkWidget* w)
{
  if (changing_state_) return;

  map<GtkWidget*,pkgCache::State::VerPriority>::const_iterator i = priorities_.find(w);
  g_return_if_fail (i != priorities_.end());
  
  pkgCache::State::VerPriority priority = i->second;
  
  changing_state_ = true;
	filter_->set_priority_filter (priority, GTK_TOGGLE_BUTTON (w)->active);
  changing_state_ = false;
}


void
GAptFilterBar::status_reverse  (GtkWidget* w)
{
  filter_->reverse_status_filter();
}

void
GAptFilterBar::status_clear    (GtkWidget* w)
{
  filter_->clear_status_filter();
}

void
GAptFilterBar::priority_reverse(GtkWidget* w)
{
  filter_->reverse_priority_filter();
}

void
GAptFilterBar::priority_clear  (GtkWidget* w)
{
  filter_->clear_priority_filter();
}

void
GAptFilterBar::all_reverse     (GtkWidget* w)
{
  filter_->reverse_entire_filter();
}

void
GAptFilterBar::all_clear       (GtkWidget* w)
{
  filter_->clear_entire_filter();
}


GtkWidget* 
GAptFilterBar::widget()
{
  return bar_;
}


