/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2012 University of Bonn. All rights reserved.
 * 
 *
 *   This file is part of MoleCuilder.
 *
 *    MoleCuilder 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.
 *
 *    MoleCuilder 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 MoleCuilder.  If not, see .
 */
/*
 * AtomIdSet.cpp
 *
 *  Created on: Feb 21, 2012
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "CodePatterns/MemDebug.hpp"
#include "AtomIdSet.hpp"
#include 
#include "Atom/atom.hpp"
#include "Descriptors/AtomIdDescriptor.hpp"
#include "Fragmentation/KeySet.hpp"
#include "World.hpp"
atom * FromIdToAtom::operator()(atomId_t id) const {
  return World::getInstance().getAtom(AtomById(id));
}
const atom * FromIdToConstAtom::operator()(atomId_t id) const {
  return const_cast(World::getInstance()).getAtom(AtomById(id));
}
/** Constructor for class AtomIdSet.
 *
 * @param _atoms atoms to put into this set
 */
AtomIdSet::AtomIdSet(const atomIdSet &_atoms) :
    atoms(_atoms)
{}
/** Constructor for class AtomIdSet.
 *
 * @param _keyset keyset to put into this set
 */
AtomIdSet::AtomIdSet(const KeySet &_keyset) :
  atoms(atomIdSet(_keyset.begin(), _keyset.end()))
{}
/** Constructor for class AtomIdSet.
 *
 * @param _atoms atoms to put into this set
 */
AtomIdSet::AtomIdSet(const std::vector &_atoms)
{
  BOOST_FOREACH(const atom * _atom, _atoms) {
    insert(_atom->getId());
  }
}
/** Constructor for class AtomIdSet.
 *
 */
AtomIdSet::AtomIdSet()
{}
/** Destructor for class AtomIdSet.
 *
 */
AtomIdSet::~AtomIdSet()
{}
/** Returns iterator to first atim via a transform_iterator.
 *
 * @return iterator to first atom in this set
 */
AtomIdSet::iterator AtomIdSet::begin(){
  return iterator(atoms.begin(), FromIdToAtom());
}
/** Returns constant iterator to first atim via a transform_iterator.
 *
 * @return const iterator to first atom in this set
 */
AtomIdSet::const_iterator AtomIdSet::begin() const{
  return const_iterator(atoms.begin(), FromIdToConstAtom());
}
/** Returns iterator to one beyond last atom via a transform_iterator.
 *
 * @return iterator to one beyond last atom in this set
 */
AtomIdSet::iterator AtomIdSet::end(){
  return iterator(atoms.end(), FromIdToAtom());
}
/** Returns constant iterator to one beyond last atom via a transform_iterator.
 *
 * @return const iterator to one beyond last atom in this set
 */
AtomIdSet::const_iterator AtomIdSet::end() const{
  return const_iterator(atoms.end(), FromIdToConstAtom());
}
/** Returns true if this set is empty.
 *
 * @return true - set is empty, false - there is at least one atom
 */
bool AtomIdSet::empty() const
{
  return (atoms.empty());
}
/** Returns the number of members of this set.
 *
 * @return number of members in set
 */
size_t AtomIdSet::size() const
{
  // set has unique members, hence just return its size
  return atoms.size();
}
/** Predicate whether given atomic id is contained.
 *
 * @param id id to check
 * @return true - is contained, false - is not
 */
bool AtomIdSet::contains(const atomId_t &id) const
{
  return (atoms.find(id) != atoms.end());
}
/** Predicate whether given atom is contained.
 *
 * @param key atom to check
 * @return true - is contained, false - is not
 */
bool AtomIdSet::contains(const atom * const key) const
{
  return contains(key->getId());
}
/** Returns the iterator to the atom \a *key.
 *
 * @param key atom to find
 * @return iterator to atom if found, to end() - else
 */
AtomIdSet::const_iterator AtomIdSet::find(const atom * const key) const
{
  return find(key->getId());
}
/** Returns the iterator to the atom \a *key.
 *
 * @param id atomic id to find
 * @return iterator to atom if found, to end() - else
 */
AtomIdSet::const_iterator AtomIdSet::find(const atomId_t &id) const
{
  return const_iterator(atoms.find(id), FromIdToConstAtom());
}
/** Inserts a given atom into the set.
 *
 * @param key atom to insert
 * @return pair of iterator and bool that states whether element is already present (true) or not (false)
 */
std::pair AtomIdSet::insert(const atom * const key)
{
  std::pair iter =
      atoms.insert(key->getId());
  std::pair retiter (std::make_pair(iterator(iter.first), iter.second));
  return retiter;
}
/** Inserts a given atom into the set.
 *
 * @param id atomic id to insert
 * @return pair of iterator and bool that states whether element is already present (true) or not (false)
 */
std::pair AtomIdSet::insert(const atomId_t &id)
{
  std::pair iter =
      atoms.insert(id);
  std::pair retiter (std::make_pair(iterator(iter.first), iter.second));
  return retiter;
}
AtomIdSet::const_iterator AtomIdSet::erase(AtomIdSet::const_iterator &loc)
{
  const_iterator iter = loc;
  ++iter;
  atom * const _atom = const_cast(*loc);
  atoms.erase( _atom->getId() );
  return iter;
}
/** Erase an atom from the list.
 *
 * @param *key key to atom in list
 * @return iterator to just after removed item (compliant with standard)
 */
AtomIdSet::const_iterator AtomIdSet::erase(const atom * const key)
{
  const_iterator iter = const_cast(*this).find(key);
  if (iter != const_cast(*this).end()){
    ++iter;
    atoms.erase( key->getId() );
  }
  return iter;
}
/** Erase an atom from the list.
 *
 * @param id atomic id atom in list to erase
 * @return iterator to just after removed item (compliant with standard)
 */
AtomIdSet::const_iterator AtomIdSet::erase(const atomId_t &id)
{
  atomIdSet::const_iterator iter = atoms.find(id);
  if (iter != atoms.end()){
    ++iter;
    atoms.erase( id );
  }
  return const_iterator(iter, FromIdToConstAtom());
}