/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#ifndef cmRange_h
#define cmRange_h

#include "cmConfigure.h" // IWYU pragma: keep

#include <algorithm>
#include <functional>
#include <iterator>

namespace RangeIterators {

template <typename Iter, typename UnaryPredicate>
class FilterIterator
{
public:
  using iterator_category = std::bidirectional_iterator_tag;
  using value_type = typename std::iterator_traits<Iter>::value_type;
  using difference_type = typename std::iterator_traits<Iter>::difference_type;
  using pointer = typename std::iterator_traits<Iter>::pointer;
  using reference = typename std::iterator_traits<Iter>::reference;

  FilterIterator(Iter b, Iter e, UnaryPredicate p)
    : Cur(std::move(b))
    , End(std::move(e))
    , Pred(std::move(p))
  {
    this->SatisfyPredicate();
  }

  FilterIterator& operator++()
  {
    ++this->Cur;
    this->SatisfyPredicate();
    return *this;
  }

  FilterIterator& operator--()
  {
    do {
      --this->Cur;
    } while (!this->Pred(*this->Cur));
    return *this;
  }

  bool operator==(FilterIterator const& other) const
  {
    return this->Cur == other.Cur;
  }

  bool operator!=(FilterIterator const& other) const
  {
    return !this->operator==(other);
  }

  auto operator*() const -> decltype(*std::declval<Iter>())
  {
    return *this->Cur;
  }

private:
  void SatisfyPredicate()
  {
    while (this->Cur != this->End && !this->Pred(*this->Cur)) {
      ++this->Cur;
    }
  }

  Iter Cur;
  Iter End;
  UnaryPredicate Pred;
};

template <typename Iter, typename UnaryFunction>
class TransformIterator
{
public:
  using iterator_category = std::bidirectional_iterator_tag;
  using value_type =
    typename std::remove_cv<typename std::remove_reference<decltype(
      std::declval<UnaryFunction>()(*std::declval<Iter>()))>::type>::type;
  using difference_type = typename std::iterator_traits<Iter>::difference_type;
  using pointer = value_type const*;
  using reference = value_type const&;

  TransformIterator(Iter i, UnaryFunction f)
    : Base(std::move(i))
    , Func(std::move(f))
  {
  }

  TransformIterator& operator++()
  {
    ++this->Base;
    return *this;
  }

  TransformIterator& operator--()
  {
    --this->Base;
    return *this;
  }

  bool operator==(TransformIterator const& other) const
  {
    return this->Base == other.Base;
  }

  bool operator!=(TransformIterator const& other) const
  {
    return !this->operator==(other);
  }

  auto operator*() const
    -> decltype(std::declval<UnaryFunction>()(*std::declval<Iter>()))
  {
    return this->Func(*this->Base);
  }

private:
  Iter Base;
  UnaryFunction Func;
};

} // namespace RangeIterators

template <typename Iter>
class cmRange
{
public:
  using const_iterator = Iter;
  using value_type = typename std::iterator_traits<Iter>::value_type;
  using difference_type = typename std::iterator_traits<Iter>::difference_type;

  cmRange(Iter b, Iter e)
    : Begin(std::move(b))
    , End(std::move(e))
  {
  }

  Iter begin() const { return this->Begin; }
  Iter end() const { return this->End; }
  bool empty() const { return this->Begin == this->End; }

  difference_type size() const
  {
    return std::distance(this->Begin, this->End);
  }

  cmRange& advance(difference_type amount) &
  {
    std::advance(this->Begin, amount);
    return *this;
  }

  cmRange advance(difference_type amount) &&
  {
    std::advance(this->Begin, amount);
    return std::move(*this);
  }

  cmRange& retreat(difference_type amount) &
  {
    std::advance(this->End, -amount);
    return *this;
  }

  cmRange retreat(difference_type amount) &&
  {
    std::advance(this->End, -amount);
    return std::move(*this);
  }

  template <typename UnaryPredicate>
  bool all_of(UnaryPredicate p) const
  {
    return std::all_of(this->Begin, this->End, std::ref(p));
  }

  template <typename UnaryPredicate>
  bool any_of(UnaryPredicate p) const
  {
    return std::any_of(this->Begin, this->End, std::ref(p));
  }

  template <typename UnaryPredicate>
  bool none_of(UnaryPredicate p) const
  {
    return std::none_of(this->Begin, this->End, std::ref(p));
  }

  template <typename UnaryPredicate>
  auto filter(UnaryPredicate p) const
    -> cmRange<RangeIterators::FilterIterator<Iter, UnaryPredicate>>
  {
    using It = RangeIterators::FilterIterator<Iter, UnaryPredicate>;
    return { It(this->Begin, this->End, p), It(this->End, this->End, p) };
  }

  template <typename UnaryFunction>
  auto transform(UnaryFunction f) const
    -> cmRange<RangeIterators::TransformIterator<Iter, UnaryFunction>>
  {
    using It = RangeIterators::TransformIterator<Iter, UnaryFunction>;
    return { It(this->Begin, f), It(this->End, f) };
  }

private:
  Iter Begin;
  Iter End;
};

template <typename Iter1, typename Iter2>
bool operator==(cmRange<Iter1> const& left, cmRange<Iter2> const& right)
{
  return left.size() == right.size() &&
    std::equal(left.begin(), left.end(), right.begin());
}

template <typename Iter1, typename Iter2>
auto cmMakeRange(Iter1 begin, Iter2 end) -> cmRange<Iter1>
{
  return { begin, end };
}

template <typename Range>
auto cmMakeRange(Range const& range) -> cmRange<decltype(range.begin())>
{
  return { range.begin(), range.end() };
}

template <typename Range>
auto cmReverseRange(Range const& range) -> cmRange<decltype(range.rbegin())>
{
  return { range.rbegin(), range.rend() };
}

#endif
