//===========================================================================
//  $Name: arts++-1-1-a12 $
//  $Id: ArtsSelectionSet.hh,v 1.2 2004/04/21 23:51:30 kkeys Exp $
//===========================================================================
//  Copyright Notice
//
//  By accessing this software, arts++, you are duly informed
//  of and agree to be bound by the conditions described below in this
//  notice:
//
//  This software product, arts++, is developed by Daniel W. McRobb, and
//  copyrighted(C) 1998 by the University of California, San Diego
//  (UCSD), with all rights reserved.  UCSD administers the CAIDA grant,
//  NCR-9711092, under which part of this code was developed.
//
//  There is no charge for arts++ software.  You can redistribute it
//  and/or modify it under the terms of the GNU Lesser General Public
//  License, Version 2.1, February 1999, which is incorporated by
//  reference herein.
//
//  arts++ is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, OF
//  MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that the use
//  of it will not infringe on any third party's intellectual
//  property rights.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with arts++.  Copies can also be obtained from:
//
//    http://www.gnu.org/copyleft/lesser.html
//
//  or by writing to:
//
//  Free Software Foundation, Inc.
//  59 Temple Place, Suite 330
//  Boston, MA 02111-1307
//  USA
//
//  Or contact:
//
//    info@caida.org
//===========================================================================

#ifndef _ARTSSELECTIONSET_HH_
#define _ARTSSELECTIONSET_HH_

extern "C" {
#include "caida_t.h"
}

#include <vector>
#include <algorithm>

#include "ArtsSelection.hh"

//---------------------------------------------------------------------------
//  template <class Type> class ArtsSelectionSet
//---------------------------------------------------------------------------
//!  This is really just a wrapper around a vector of ArtsSelection
//!  objects.
//---------------------------------------------------------------------------
template <class Type>
class ArtsSelectionSet : public std::vector<ArtsSelection<Type> >
{
public:
  //-------------------------------------------------------------------------
  //                       Type & Add(const Type & value)
  //.........................................................................
  //!  Adds a single value to the selection set.  Returns the
  //!  ArtsSelection<Type> that is inserted into the set.
  //-------------------------------------------------------------------------
  ArtsSelection<Type> & Add(const Type & value)
  {
    this->push_back(ArtsSelection<Type>(value));
    return(*(this->rbegin()));
  }
  
  //-------------------------------------------------------------------------
  //     const ArtsSelection<Type> & AddRange(const Type & firstValue,
  //                                          const Type & lastValue)
  //.........................................................................
  //!  Adds a range selection to the selection set.  Returns a reference
  //!  to the range selection.
  //-------------------------------------------------------------------------
  const ArtsSelection<Type> & AddRange(const Type & firstValue,
                                       const Type & lastValue)
  {
    this->push_back(ArtsSelection<Type>(firstValue,lastValue));
    return(*(this->rbegin()));
  }
  
  //-------------------------------------------------------------------------
  //                  bool Matches(const Type & value) const
  //.........................................................................
  //!  Returns true if value is in the selection set (in a range or
  //!  matching one of our single values), else returns false.
  //-------------------------------------------------------------------------
  bool Matches(const Type & value) const
  {
    typename ArtsSelectionSet<Type>::const_iterator  selectionIter;
    bool            rc = false;

    for (selectionIter = this->begin(); selectionIter != this->end();
         selectionIter++) {
      if ((*selectionIter).Matches(value)) {
        rc = true;
        break;
      }
    }
    return(rc);
  }

  //-------------------------------------------------------------------------
  //     bool operator == (const ArtsSelectionSet & selectionSet) const
  //.........................................................................
  //!  Compares two ArtsSelectionSet objects, independent of the order
  //!  of their contained selections.  It uses sort(), unique() and the
  //!  vector == operator to do this.
  //-------------------------------------------------------------------------
  bool operator == (const ArtsSelectionSet & selectionSet) const
  {
    ArtsSelectionSet  thisTmpSelectionSet = (*this);
    ArtsSelectionSet  tmpSelectionSet = selectionSet;
    
    sort(thisTmpSelectionSet.begin(),thisTmpSelectionSet.end());
    unique(thisTmpSelectionSet.begin(),thisTmpSelectionSet.end());
    sort(tmpSelectionSet.begin(),tmpSelectionSet.end());
    unique(tmpSelectionSet.begin(),tmpSelectionSet.end());

    if (tmpSelectionSet.size() != thisTmpSelectionSet.size())
      return(false);

    bool rc = true;
    for (int i = 0; i < thisTmpSelectionSet.size(); i++) {
      if (thisTmpSelectionSet[i] != tmpSelectionSet[i]) {
        rc = false;
        break;
      }
    }
    return(rc);
  }
};

#endif  // _ARTSSELECTIONSET_HH_
