// =====================================================================================================================
//  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/>.
// =====================================================================================================================

#ifndef FENNEC_LANG_DETAIL_TYPE_TRAITS_H
#define FENNEC_LANG_DETAIL_TYPE_TRAITS_H

#include <fennec/lang/constants.h>
#include <fennec/lang/float.h>

namespace fennec
{

namespace detail
{

// Nothing interesting to note here
template<typename> struct __is_void       : false_type {};
template<>         struct __is_void<void> : true_type {};

template<typename> struct __is_bool         : false_type {};
template<>         struct __is_bool<bool_t> : true_type {};

template<typename> struct __is_null_pointer            : false_type {};
template<>         struct __is_null_pointer<nullptr_t> : true_type {};

// Provides definitions for all builtin int types
template<typename> struct __is_integral           : false_type {};
template<>         struct __is_integral<bool_t>   : true_type {};
template<>         struct __is_integral<char_t>   : true_type {};
template<>         struct __is_integral<char8_t>  : true_type {};
template<>         struct __is_integral<char16_t> : true_type {};
template<>         struct __is_integral<char32_t> : true_type {};
template<>         struct __is_integral<schar_t>  : true_type {};
template<>         struct __is_integral<uchar_t>  : true_type {};
template<>         struct __is_integral<wchar_t>  : true_type {};
template<>         struct __is_integral<short_t>  : true_type {};
template<>         struct __is_integral<ushort_t> : true_type {};
template<>         struct __is_integral<int_t>    : true_type {};
template<>         struct __is_integral<uint_t>   : true_type {};
template<>         struct __is_integral<long_t>   : true_type {};
template<>         struct __is_integral<ulong_t>  : true_type {};
template<>         struct __is_integral<llong_t>  : true_type {};
template<>         struct __is_integral<ullong_t> : true_type {};

// Most unsigned types will underflow `-1` to the types maximum value
template<typename TypeT> struct __is_signed   : bool_constant<TypeT(-1) < TypeT(0)> {};
template<typename TypeT> struct __is_unsigned : bool_constant<TypeT(-1) >= TypeT(0)> {};

template<typename> struct __is_floating_point           : false_type {};
template<>         struct __is_floating_point<float_t>  : true_type {};
template<>         struct __is_floating_point<double_t> : true_type {};

}

}

#endif // FENNEC_LANG_DETAIL_TYPE_TRAITS_H
