// =====================================================================================================================
//  fennec, a free and open source game engine
//  Copyright © 2025  Medusa Slockbower
//
//  This program 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 3 of the License, or
//  (at your option) any later version.
//
//  This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================

///
/// \file type_sequences.h
/// \brief \ref fennec_lang_type_sequences
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///

#ifndef FENNEC_LANG_TYPE_SEQUENCES_H
#define FENNEC_LANG_TYPE_SEQUENCES_H

///
/// \page fennec_lang_type_sequences Type Sequences
///
/// \brief This header is part of the metaprogramming library. It defines structures for sequences of types, used during compile time.
///
/// \code #include <fennec/lang/type_sequences.h> \endcode
///
/// <table width="100%" class="fieldtable" id="table_fennec_lang_type_sequences">
/// <tr><th style="vertical-align: top">Syntax
///     <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::first_element "typename first_element<ValueT, Values...>::type"<br>
///         \ref fennec::first_element_t "first_element_t<ValueT, Values...>"
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::first_element
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::replace_first_element "typename replace_first_element<ClassT, SubT, OriginT, RestT...>::type"<br>
///     <td width="50%" style="vertical-align: top">
///         \copydoc fennec::replace_first_element
/// </table>
///

#include <fennec/lang/detail/_type_sequences.h>

namespace fennec
{

///
/// \brief Get the first element of a template parameter pack
/// \tparam TypesT the Parameter Pack
template<typename...TypesT> struct first_element : detail::_first_element<TypesT...> {};

///
/// \brief alias for first_element<TypesT>::type
template<typename...TypesT> using first_element_t = typename first_element<TypesT...>::type;


template<size_t n, typename...TypesT> struct nth_element : detail::_nth_element<n, 0, TypesT...> {};


///
/// \brief Take a Template with a Pack `ClassT<ArgsT...>` and replace the first `ArgT` of `ArgsT...` with `SubT`
template<typename ClassT, typename SubT> struct replace_first_element { };

// Implementation
template<
	template<typename, typename...> class ClassT              // The Base Template
,	typename SubT, typename OriginT                           // The Original Type and Type to Substitute
,	typename... RestT>                                        // The Rest of the Parameter Pack
struct replace_first_element<ClassT<OriginT, RestT...>, SubT> // Specialization
	{ using type = ClassT<SubT, RestT...>; };                 // Definition

}


#endif // FENNEC_LANG_VARIADICS_H
