#pragma once
#include "SafeMultiset.h"
#include <boost/iterator/filter_iterator.hpp>

template <class T, class Compare = std::less<T>>
class ConstSafeMultisetAdaptor
{
protected:
  struct NotDeleted
  {
    bool operator()(const typename SafeMultiset<T, Compare>::Wrapper& wrapper) const
    {
      return !wrapper.isDeleted();
    }
  };
public:
  typedef boost::filter_iterator<NotDeleted, typename SafeMultiset<T, Compare>::internal_const_iterator> const_iterator;

  ConstSafeMultisetAdaptor(const SafeMultiset<T, Compare>& safeMultiset)
    : m_safeMultiset(safeMultiset)
  {
    //assert(safeMultiset.m_nbCurrentIterations == 0);
  }
  const_iterator unsafe_begin() const { return const_iterator(NotDeleted(), m_safeMultiset.m_multiset.begin(), m_safeMultiset.m_multiset.end()); }
  const_iterator unsafe_end() const { return const_iterator(NotDeleted(), m_safeMultiset.m_multiset.end(), m_safeMultiset.m_multiset.end()); }

protected:
  const SafeMultiset<T, Compare>& m_safeMultiset;
private:
  ConstSafeMultisetAdaptor & operator=(const ConstSafeMultisetAdaptor &);
};

template <class T, class Compare = std::less<T>>
class SafeMultisetAdaptor : public ConstSafeMultisetAdaptor<T, Compare>
{
public:
  typedef boost::filter_iterator<NotDeleted, typename SafeMultiset<T, Compare>::internal_iterator> iterator;

  SafeMultisetAdaptor(SafeMultiset<T, Compare>& safeMultiset)
    : ConstSafeMultisetAdaptor(safeMultiset)
    , m_safeMultiset(safeMultiset)
  {}
  iterator unsafe_begin() { return iterator(NotDeleted(), m_safeMultiset.m_multiset.begin(), m_safeMultiset.m_multiset.end()); }
  iterator unsafe_end() { return iterator(NotDeleted(), m_safeMultiset.m_multiset.end(), m_safeMultiset.m_multiset.end()); }

protected:
  SafeMultiset<T, Compare>& m_safeMultiset;
};