// Boost.Range library
//
//  Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and
//  distribution is subject to the Boost Software License, Version
//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_ADAPTOR_ADJACENT_FILTER_IMPL_HPP
#define BOOST_RANGE_ADAPTOR_ADJACENT_FILTER_IMPL_HPP

#include <boost/config.hpp>
#ifdef BOOST_MSVC
#pragma warning( push )
#pragma warning( disable : 4355 )
#endif

#include <boost/range/adaptor/argument_fwd.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/next_prior.hpp>


namespace boost
{
    namespace range_detail
    {
        template< class Iter, class Pred, bool default_pass >
        class skip_iterator
          : public boost::iterator_adaptor<
                    skip_iterator<Iter,Pred,default_pass>,
                    Iter,
                    BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::value_type,
                    boost::forward_traversal_tag,
                    BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::reference,
                    BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::difference_type
                >
          , private Pred
        {
        private:
            typedef boost::iterator_adaptor<
                        skip_iterator<Iter,Pred,default_pass>,
                        Iter,
                        BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::value_type,
                        boost::forward_traversal_tag,
                        BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::reference,
                        BOOST_DEDUCED_TYPENAME std::iterator_traits<Iter>::difference_type
                    > base_t;

        public:
            typedef Pred pred_t;
            typedef Iter iter_t;

            skip_iterator() : m_last() {}

            skip_iterator(iter_t it, iter_t last, const Pred& pred)
                : base_t(it)
                , pred_t(pred)
                , m_last(last)
            {
                move_to_next_valid();
            }

            template<class OtherIter>
            skip_iterator( const skip_iterator<OtherIter, pred_t, default_pass>& other )
            : base_t(other.base())
            , pred_t(other)
            , m_last(other.m_last) {}

            void move_to_next_valid()
            {
                iter_t& it = this->base_reference();
                pred_t& bi_pred = *this;
                if (it != m_last)
                {
                    if (default_pass)
                    {
                        iter_t nxt = ::boost::next(it);
                        while (nxt != m_last && !bi_pred(*it, *nxt))
                        {
                            ++it;
                            ++nxt;
                        }
                    }
                    else
                    {
                        iter_t nxt = ::boost::next(it);
                        for(; nxt != m_last; ++it, ++nxt)
                        {
                            if (bi_pred(*it, *nxt))
                            {
                                break;
                            }
                        }
                        if (nxt == m_last)
                        {
                            it = m_last;
                        }
                    }
                }
            }

            void increment()
            {
                iter_t& it = this->base_reference();
                BOOST_ASSERT( it != m_last );
                ++it;
                move_to_next_valid();
            }

            iter_t m_last;
        };

        template< class P, class R, bool default_pass >
        struct adjacent_filter_range
            : iterator_range< skip_iterator<
                                BOOST_DEDUCED_TYPENAME range_iterator<R>::type,
                                P,
                                default_pass
                            >
                        >
        {
        private:
            typedef skip_iterator<
                        BOOST_DEDUCED_TYPENAME range_iterator<R>::type,
                        P,
                        default_pass
                     >
                skip_iter;

            typedef iterator_range<skip_iter>
                base_range;

            typedef BOOST_DEDUCED_TYPENAME range_iterator<R>::type raw_iterator;

        public:
            adjacent_filter_range( const P& p, R& r )
            : base_range(skip_iter(boost::begin(r), boost::end(r), p),
                         skip_iter(boost::end(r), boost::end(r), p))
            {
            }

        private:
            P m_pred;
            R* m_range;
        };

        template< class T >
        struct adjacent_holder : holder<T>
        {
            adjacent_holder( T r ) : holder<T>(r)
            { }
        };

        template< class T >
        struct adjacent_excl_holder : holder<T>
        {
            adjacent_excl_holder( T r ) : holder<T>(r)
            { }
        };

        template< class ForwardRng, class BinPredicate >
        inline adjacent_filter_range<BinPredicate, ForwardRng, true>
        operator|( ForwardRng& r,
                   const adjacent_holder<BinPredicate>& f )
        {
            return adjacent_filter_range<BinPredicate, ForwardRng, true>( f.val, r );
        }

        template< class ForwardRng, class BinPredicate >
        inline adjacent_filter_range<BinPredicate, const ForwardRng, true>
        operator|( const ForwardRng& r,
                   const adjacent_holder<BinPredicate>& f )
        {
            return adjacent_filter_range<BinPredicate,
                                         const ForwardRng, true>( f.val, r );
        }

        template< class ForwardRng, class BinPredicate >
        inline adjacent_filter_range<BinPredicate, ForwardRng, false>
        operator|( ForwardRng& r,
                   const adjacent_excl_holder<BinPredicate>& f )
        {
            return adjacent_filter_range<BinPredicate, ForwardRng, false>( f.val, r );
        }

        template< class ForwardRng, class BinPredicate >
        inline adjacent_filter_range<BinPredicate, ForwardRng, false>
        operator|( const ForwardRng& r,
                   const adjacent_excl_holder<BinPredicate>& f )
        {
            return adjacent_filter_range<BinPredicate,
                                         const ForwardRng, false>( f.val, r );
        }

    } // 'range_detail'

    // Bring adjacent_filter_range into the boost namespace so that users of
    // this library may specify the return type of the '|' operator and
    // adjacent_filter()
    using range_detail::adjacent_filter_range;

    namespace adaptors
    {
        namespace
        {
            const range_detail::forwarder<range_detail::adjacent_holder>
                adjacent_filtered =
                   range_detail::forwarder<range_detail::adjacent_holder>();

            const range_detail::forwarder<range_detail::adjacent_excl_holder>
                adjacent_filtered_excl =
                    range_detail::forwarder<range_detail::adjacent_excl_holder>();
        }

        template<class ForwardRng, class BinPredicate>
        inline adjacent_filter_range<BinPredicate, ForwardRng, true>
        adjacent_filter(ForwardRng& rng, BinPredicate filter_pred)
        {
            return adjacent_filter_range<BinPredicate, ForwardRng, true>(filter_pred, rng);
        }

        template<class ForwardRng, class BinPredicate>
        inline adjacent_filter_range<BinPredicate, const ForwardRng, true>
        adjacent_filter(const ForwardRng& rng, BinPredicate filter_pred)
        {
            return adjacent_filter_range<BinPredicate, const ForwardRng, true>(filter_pred, rng);
        }

    } // 'adaptors'

}

#ifdef BOOST_MSVC
#pragma warning( pop )
#endif

#endif
