// =====================================================================================================================
//  fennec, a free and open source game engine
//  Copyright © 2025 - 2026  Medusa Slockbower
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General 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 License for more details.
//
//  You should have received a copy of the GNU General License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================

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

#ifndef FENNEC_LANG_TYPE_TRANSFORMS_H
#define FENNEC_LANG_TYPE_TRANSFORMS_H

#include <fennec/lang/conditional_types.h>
#include <fennec/lang/type_identity.h>
#include <fennec/lang/detail/_type_traits.h>
#include <fennec/lang/detail/_type_transforms.h>

///
/// \page fennec_lang_type_transforms Type Transforms
///
/// \brief Part of the fennec metaprogramming library. This header defines structures for copying types with different traits
///        or rather, transform them, at compile time.
///
/// \code #include <fennec/lang/type_transforms.h> \endcode
///
/// \section fennec_lang_type_transforms_section_decay_conversions Decay Conversions
///
/// <table width="100%" class="fieldtable" id="fennec_lang_type_transforms_decay_conversions">
/// <tr><th style="vertical-align: top">Syntax
///     <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::decay "decay<TypeT>::type"<br>
///         \ref fennec::decay_t "decay_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::decay
///
/// </table>
///
/// \section fennec_lang_type_transforms_section_pointer_conversions Pointer Conversions
///
/// <table width="100%" class="fieldtable" id="fennec_lang_type_transforms_pointer_conversions">
/// <tr><th style="vertical-align: top">Syntax
///     <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::add_pointer "add_pointer<TypeT>::type"<br>
///         \ref fennec::add_pointer_t "add_pointer_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::add_pointer
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::remove_pointer "remove_pointer<TypeT>::type"<br>
///         \ref fennec::remove_pointer_t "remove_pointer_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::remove_pointer
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::strip_pointers "strip_pointers<TypeT>::type"<br>
///         \ref fennec::strip_pointers_t "strip_pointers<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::strip_pointers
///
/// </table>
///
/// \section fennec_lang_type_transforms_section_reference_conversions Reference Conversions
///
/// <table width="100%" class="fieldtable" id="fennec_lang_type_transforms_reference_conversions">
/// <tr><th style="vertical-align: top">Syntax
///     <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::add_reference "add_reference<TypeT>::type"<br>
///         \ref fennec::add_reference_t "add_reference_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::add_reference
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::add_lvalue_reference "add_lvalue_reference<TypeT>::type"<br>
///         \ref fennec::add_lvalue_reference_t "add_lvalue_reference_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::add_lvalue_reference
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::add_rvalue_reference "add_rvalue_reference<TypeT>::type"<br>
///         \ref fennec::add_rvalue_reference_t "add_rvalue_reference_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::add_rvalue_reference
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::remove_reference "remove_reference<TypeT>::type"<br>
///         \ref fennec::remove_reference_t "remove_reference_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::remove_reference
///
/// </table>
///
/// \section fennec_lang_type_transforms_section_cv_conversions Const — Volatile Conversions
///
/// <table width="100%" class="fieldtable" id="fennec_lang_type_transforms_cv_conversions">
/// <tr><th style="vertical-align: top">Syntax
///     <th style="vertical-align: top">Description
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::add_const "add_const<TypeT>::type"<br>
///         \ref fennec::add_const_t "add_const_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::add_const
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::remove_const "remove_const<TypeT>::type"<br>
///         \ref fennec::remove_const_t "remove_const_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::remove_const
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::add_volatile "add_volatile<TypeT>::type"<br>
///         \ref fennec::add_volatile_t "add_volatile_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::add_volatile
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::remove_volatile "remove_volatile<TypeT>::type"<br>
///         \ref fennec::remove_volatile_t "remove_volatile_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::remove_volatile
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::add_cv "add_cv<TypeT>::type"<br>
///         \ref fennec::add_cv_t "add_cv_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::add_cv
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::remove_cv "remove_cv<TypeT>::type"<br>
///         \ref fennec::remove_cv_t "remove_cv_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::remove_cv
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::add_cvref "add_cvref<TypeT>::type"<br>
///         \ref fennec::add_cvref_t "add_cvref_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::add_cvref
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::remove_cvref "remove_cvref<TypeT>::type"<br>
///         \ref fennec::remove_cvref_t "remove_cvref_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::remove_cvref
///
/// <tr><td width="50%" style="vertical-align: top"> <br>
///         \ref fennec::remove_cvrefptr "remove_cvrefptr<TypeT>::type"<br>
///         \ref fennec::remove_cvrefptr_t "remove_cvrefptr_t<TypeT>"
///     <td width="50%" style="vertical-align: top">
///         \copydetails fennec::remove_cvrefptr
///
/// </table>
///


namespace fennec
{

// Decay Conversions ===================================================================================================

///
/// \brief decays a type into its most basic form
/// \tparam T the type to decay
template<typename T> struct decay : detail::_decay<T> {};

///
/// \brief shorthand for `typename decay<T>::type`
/// \tparam T the type to decay
template<typename T> using decay_t = typename decay<T>::type;

// Pointer Conversions =================================================================================================

///
/// \brief adds a pointer level to \emph{T}
///
/// \details adds a pointer to the provided type such that \emph{T} becomes \emph{T*}
/// \tparam T Resultant Type
template<typename T> struct add_pointer : detail::_add_pointer<T>{};

///
/// \brief shorthand for `typename add_pointer<T>::type`
template<typename T> using add_pointer_t = typename add_pointer<T>::type;


///
/// \brief removes a pointer level from \emph{T}
///
/// \details removes a pointer from the provided type such that \emph{T*} becomes \emph{T}
/// \tparam T Resultant Type
template<typename T> struct remove_pointer : detail::_remove_pointer<T> {};

///
/// \brief shorthand for `typename remove_pointer<T>::type`
template<typename T> using remove_pointer_t = typename remove_pointer<T>::type;


///
/// \brief removes all pointer levels from \emph{T}
///
/// \details removes all pointers from the provided type such that \emph{T*}, \emph{T**}, etc. becomes \emph{T}
/// \tparam T Resultant Type
template<typename T> struct strip_pointers : conditional_t<
			detail::_is_pointer<T>::value,
			strip_pointers<remove_pointer_t<T>>,
			type_identity<T>
		> {};

///
/// \brief shorthand for `typename strip_pointers<T>::type`
template<typename T> using strip_pointers_t = strip_pointers<T>::type;



// Reference Conversions ===============================================================================================

///
/// \brief add a reference to \emph{T}
///
/// \details adds a pointer to the provided type such that \emph{T} becomes \emph{T\&}
/// \tparam T Resultant Type
template<typename T> struct add_reference : type_identity<T&> {};

///
/// \brief shorthand for `typename fennec::add_reference<T>::type`
template<typename T> using  add_reference_t = typename add_reference<T>::type;


///
/// \brief add a lvalue reference to \emph{T}
///
/// \details adds a lvalue reference to the provided type such that \emph{T} becomes \emph{T\&}
/// \tparam T Reference Type
template<typename T> struct add_lvalue_reference : detail::_add_lvalue_reference<T> {};

///
/// \brief shorthand for `typename fennec::add_lvalue_reference<T>::type`
template<typename T> using  add_lvalue_reference_t = typename add_lvalue_reference<T>::type;


///
/// \brief add a rvalue reference to \emph{T}
///
/// \details adds a rvalue reference to the provided type such that \emph{T} becomes \emph{T\&\&}
/// \tparam T Reference Type
template<typename T> struct add_rvalue_reference : detail::_add_rvalue_reference<T> {};

///
/// \brief shorthand for `typename fennec::add_rvalue_reference<T>::type`
template<typename T> using  add_rvalue_reference_t = typename add_rvalue_reference<T>::type;


///
/// \brief remove a reference from \emph{T}
///
/// \details removes references from the provided type such that \emph{T\&} and \emph{T\&\&} become \emph{T}
/// \tparam T Reference Type
template<typename T> struct remove_reference : type_identity<T> {};

// specialization for T&
template<typename T> struct remove_reference<T&> : type_identity<T> {};

// specialization for T&&
template<typename T> struct remove_reference<T&&> : type_identity<T> {};

///
/// \brief shorthand for `typename fennec::remove_reference<T>::type`
template<typename T> using  remove_reference_t = typename remove_reference<T>::type;



// Const & Volatile Conversions ========================================================================================

///
/// \brief add the const qualifier to the provided type \emph{T}
///
/// \details adds const qualification to the provided type such that \emph{T} becomes \emph{const\quad T}
/// \tparam T Reference Type
template<typename T> struct add_const : detail::_add_const<T> {};

///
/// \brief shorthand for `typename fennec::add_const<T>::type`
template<typename T> using add_const_t = typename add_const<T>::type;


///
/// \brief remove the const qualifier from the provided type \emph{T}
///
/// \details removes const qualification from the provided type such that \emph{const\quad T} becomes \emph{T}
/// \tparam T Reference Type
template<typename T> struct remove_const : detail::_remove_const<T> {};

///
/// \brief shorthand for `typename fennec::remove_const<T>::type`
template<typename T> using remove_const_t = typename remove_const<T>::type;



///
/// \brief add the volatile qualifier to the provided type \emph{T}
///
/// \details removes references from the provided type such that \emph{T} becomes \emph{volatile\quad T}
/// \tparam T Reference Type
template<typename T> struct add_volatile : detail::_add_volatile<T> {};

///
/// \brief shorthand for `typename fennec::add_volatile<T>::type`
template<typename T> using add_volatile_t = typename add_volatile<T>::type;


///
/// \brief remove the volatile qualifier from the provided type \emph{T}
///
/// \details removes references from the provided type such that \emph{volatile\quad T} becomes \emph{T}
/// \tparam T Reference Type
template<typename T> struct remove_volatile : detail::_remove_volatile<T> {};

///
/// \brief shorthand for `typename fennec::remove_volatile<T>::type`
template<typename T> using remove_volatile_t = typename remove_volatile<T>::type;



///
/// \brief remove the volatile qualifier from the provided type \emph{T}
///
/// \details removes references from the provided type such that \emph{T}, \emph{const\quad T}, and \emph{volatile\quad T}
///			 become \emph{const volatile T}
/// \tparam T Reference Type
template<typename T> struct add_cv : detail::_add_cv<T> {};

///
/// \brief shorthand for `typename fennec::add_cv<T>::type`
template<typename T> using add_cv_t = typename add_cv<T>::type;



///
/// \brief remove the const and volatile qualifiers from the provided type \emph{T}
///
/// \details removes const and volatile from the provided type such that \emph{const\quad T}, \emph{volatile\quad T}, and
///          \emph{const\quad volatile\quad T} become \emph{T}
/// \tparam T Reference Type
template<typename T> struct remove_cv : detail::_remove_cv<T> {};

///
/// \brief shorthand for `typename fennec::remove_cv<T>::type`
template<typename T> using remove_cv_t = typename remove_cv<T>::type;



///
/// \brief add a reference and the const volatile qualifiers from the provided type \emph{T}
///
/// \details adds references and const volatile qualifiers to the provided type.
/// \tparam T Reference Type
template<typename T> struct add_cvref : type_identity<add_reference_t<add_cv_t<T>>> {};

///
/// \brief shorthand for `typename fennec::add_cvr<T>::type`
template<typename T> using add_cvref_t = typename add_cvref<T>::type;



///
/// \brief removes references as well as the const and volatile qualifiers from the provided type \emph{T}
///
/// \details removes const and volatile from the provided type such that
/// \tparam T Reference Type
template<typename T> struct remove_cvref : type_identity<remove_cv_t<remove_reference_t<T>>> {};


///
/// \brief shorthand for `typename fennec::remove_cvr<T>::type`
template<typename T> using remove_cvref_t = typename remove_cvref<T>::type;



///
/// \brief removes references and pointers as well as the const and volatile qualifiers from the provided type \emph{T}
///
/// \details removes const and volatile from the provided type such that
/// \tparam T Reference Type
template<typename T> struct remove_cvrefptr : type_identity<remove_cv_t<remove_reference_t<strip_pointers_t<T>>>> {};


///
/// \brief shorthand for `typename fennec::remove_cvrp_t<T>::type`
template<typename T> using remove_cvrefptr_t = typename remove_cvrefptr<T>::type;

}

#endif // FENNEC_LANG_TYPE_TRANSFORMS_H
