// -*- C++ -*-
// -----------------------------------------------------------------------------------------------------
// Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
// Copyright (c) 2016-2020, Knut Reinert & MPI für molekulare Genetik
// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
// -----------------------------------------------------------------------------------------------------

/*!\file
 * \brief Adaptations of concepts from the Ranges TS
 * \author Hannes Hauswedell <hannes.hauswedell AT fu-berlin.de>
 */

#pragma once

#include <seqan3/range/detail/enable_view.hpp>

#if __cpp_lib_ranges // C++20 ranges available
#include <ranges>
#else // implement via range-v3

//!\cond
#ifndef RANGES_DEEP_STL_INTEGRATION
#define RANGES_DEEP_STL_INTEGRATION 1
#endif
//!\endcond

#include <range/v3/range/concepts.hpp>
#include <range/v3/iterator/insert_iterators.hpp>
#include <range/v3/view/all.hpp>
#include <range/v3/view/any_view.hpp>
#include <range/v3/view/common.hpp>
#include <range/v3/view/drop.hpp>
#include <range/v3/view/drop_while.hpp>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/iota.hpp>
#include <range/v3/view/istream.hpp>
#include <range/v3/view/join.hpp>
#include <range/v3/view/reverse.hpp>
#include <range/v3/view/single.hpp>
#include <range/v3/view/split.hpp>
#include <range/v3/view/subrange.hpp>
#include <range/v3/view/take.hpp>
#include <range/v3/view/take_while.hpp>
#include <range/v3/view/transform.hpp>

#include <seqan3/core/type_traits/transformation_trait_or.hpp>
#include <seqan3/std/concepts>
#include <seqan3/std/iterator>

// ============================================================================
//  namespace aliasing
// ============================================================================

/*!\defgroup ranges ranges
 * \ingroup std
 * \brief The \<ranges\> header from C++20's standard library.
 */

namespace std::ranges
{

namespace
{

using namespace ::ranges::cpp20;

} // anonymous namespace

} // namespace std::ranges

namespace std
{

namespace views = ranges::views;

} // namespace std::

// ============================================================================
//  traits voodoo
// ============================================================================

namespace ranges
{

//!\brief Customises ranges type trait that indicates whether `type` is a view.
template <typename type>
//!\cond
    requires (seqan3::detail::enable_view<type> == 0) || (seqan3::detail::enable_view<type> == 1)
//!\endcond
constexpr bool enable_view<type> = static_cast<bool>(seqan3::detail::enable_view<type>);

} // namespace ranges

#endif // no standard header

#if __cpp_lib_ranges

namespace std::ranges
{

//!\brief Customises std::ranges type trait that indicates whether `type` is a view.
template <typename type>
//!\cond
    requires (seqan3::detail::enable_view<type> == 0) || (seqan3::detail::enable_view<type> == 1)
//!\endcond
constexpr bool enable_view<type> = static_cast<bool>(seqan3::detail::enable_view<type>);

} // namespace std::ranges

#endif // standard header
