/** -*- Mode: C++; tab-width: 4 -*-
 * vim: sw=4 ts=4:
 *
 * Gnome Apt filter class
 *
 * 	(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 "filter.h"
#include "pkgutil.h"
#include "search.h"

Filter::Filter()
  : status_default_(true),
    priority_default_(true),
	f_search (0)
{
}

void 
Filter::reverse_entire_filter()
{
  reverse_status_filter(false);
  reverse_priority_filter(false);
  
  change_notify();
}

void 
Filter::clear_entire_filter()
{
  clear_status_filter(false);
  clear_priority_filter(false);

  change_notify();
}

static void
search_changed_cb (GtkWidget* wdg, Filter* f) {
	f->change_notify();
}

void
Filter::set_search_filter (GAptSearch* s) {
	f_search = s;
	if (s) {
		g_signal_connect (G_OBJECT (s), "filter-changed", G_CALLBACK (search_changed_cb), this);
	}
}

bool
Filter::get_search_filter (pkgCache::Package* p) {
	if (!f_search) {
		return true;
	}
	return f_search->filter_package (p);
}

bool 
Filter::include_package(pkgCache::PkgIterator & i, GAptCache* cache)
{
	GAptCache::PkgStatusType status = cache->pkgStatus (i);

  if (get_status_filter(status) == false) return false;

	pkgCache::State::VerPriority p;
	cache->priorityString (i, &p);

  if (get_priority_filter(p) == false) return false;

	pkgCache::Package* pkg = (pkgCache::Package*) i;
	if (get_search_filter (pkg) == false) {
		return false;
	}

  // didn't find any falses
  return true;
}

void
Filter::set_status_filter (GAptCache::PkgStatusType st, bool state) {
  status_[st] = state;
  change_notify();
}


void 
Filter::reverse_status_filter(bool notify)
{
	map<GAptCache::PkgStatusType, bool>::iterator j = status_.begin();
  while (j != status_.end()) 
    {
      j->second = !j->second;
      ++j;
    }

  status_default_ = !status_default_;

  if (notify) change_notify();
}

void 
Filter::clear_status_filter(bool notify)
{
	map<GAptCache::PkgStatusType, bool>::iterator j = status_.begin();
  while (j != status_.end()) 
    {
      j->second = true;
      ++j;
    }

  status_default_ = true;

  if (notify) change_notify();
}

void 
Filter::set_priority_filter(pkgCache::State::VerPriority p, bool state)
{
  priority_[p] = state;
  change_notify();
}


void 
Filter::reverse_priority_filter(bool notify)
{
  map<pkgCache::State::VerPriority,bool>::iterator k = priority_.begin();
  while (k != priority_.end()) 
    {
      k->second = !k->second;
      ++k;
    }

  priority_default_ = !priority_default_;

  if (notify) change_notify();
}

void 
Filter::clear_priority_filter(bool notify)
{
  map<pkgCache::State::VerPriority,bool>::iterator k = priority_.begin();
  while (k != priority_.end()) 
    {
      k->second = true;
      ++k;
    }

  priority_default_ = true;

  if (notify) change_notify();
}

bool
Filter::get_status_filter (GAptCache::PkgStatusType st) const {
	map<GAptCache::PkgStatusType, bool>::const_iterator j = status_.find (st);
  if (j != status_.end()) {
    return j->second;
  }
  else return status_default_;
}

bool 
Filter::get_priority_filter(pkgCache::State::VerPriority p) const
{
  map<pkgCache::State::VerPriority,bool>::const_iterator k = priority_.find(p);
  
  if (k != priority_.end()) {
    return k->second;
  }
  else return priority_default_;
}

void 
Filter::add_view(View* v) 
{
#ifdef GNOME_ENABLE_DEBUG
  set<View*>::iterator i = views_.find(v);
  if (i != views_.end()) g_warning("Adding view twice!");
#endif
  views_.insert(v);
}
  
void 
Filter::remove_view(View* v) 
{
  set<View*>::iterator i = views_.find(v);
  if (i != views_.end())
    views_.erase(i);
#ifdef GNOME_ENABLE_DEBUG
  else g_warning("View not in list!");
#endif
}


void 
Filter::change_notify() 
{
  set<View*>::iterator i = views_.begin();
  while (i != views_.end())
    {
      (*i)->filter_changed();
      ++i;
    }
}
