// =====================================================================================================================
//  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_METAPROGRAMMING_INTEGER_H
#define FENNEC_METAPROGRAMMING_INTEGER_H

#include <fstream>

inline void integer_h()
{

	std::ofstream out("integer.h");

	out << "// =====================================================================================================================" << std::endl;
	out << "//  fennec, a free and open source game engine" << std::endl;
	out << "//  Copyright © 2025  Medusa Slockbower" << std::endl;
	out << "//" << std::endl;
	out << "//  This program is free software: you can redistribute it and/or modify" << std::endl;
	out << "//  it under the terms of the GNU General Public License as published by" << std::endl;
	out << "//  the Free Software Foundation, either version 3 of the License, or" << std::endl;
	out << "//  (at your option) any later version." << std::endl;
	out << "//" << std::endl;
	out << "//  This program is distributed in the hope that it will be useful," << std::endl;
	out << "//  but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl;
	out << "//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the" << std::endl;
	out << "//  GNU General Public License for more details." << std::endl;
	out << "//" << std::endl;
	out << "//  You should have received a copy of the GNU General Public License" << std::endl;
	out << "//  along with this program.  If not, see <https://www.gnu.org/licenses/>." << std::endl;
	out << "// =====================================================================================================================" << std::endl;

	out << "" << std::endl;

	out << "///" << std::endl;
	out << "/// \\file integer.h" << std::endl;
	out << "/// \\brief metaprogramming integer type info" << std::endl;
	out << "///" << std::endl;
	out << "///" << std::endl;
	out << "/// \\details this file is automatically generated for the current build environment" << std::endl;
	out << "///" << std::endl;
	out << "/// \\copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))" << std::endl;
	out << "///" << std::endl;
	out << "///" << std::endl;

	out << "" << std::endl;

	out << "#ifndef FENNEC_LANG_INTEGER_H" << std::endl;
	out << "#define FENNEC_LANG_INTEGER_H" << std::endl;

	out << "" << std::endl;

	out << "#undef CHAR_MIN" << std::endl;
	out << "#undef CHAR_MAX" << std::endl;
	out << "#undef WCHAR_MIN" << std::endl;
	out << "#undef WCHAR_MAX" << std::endl;
	out << "#undef SCHAR_MIN" << std::endl;
	out << "#undef SCHAR_MAX" << std::endl;
	out << "#undef UCHAR_MIN" << std::endl;
	out << "#undef UCHAR_MAX" << std::endl;
	out << "#undef INT_MIN" << std::endl;
	out << "#undef INT_MAX" << std::endl;
	out << "#undef UINT_MIN" << std::endl;
	out << "#undef UINT_MAX" << std::endl;
	out << "#undef LONG_MIN" << std::endl;
	out << "#undef LONG_MAX" << std::endl;
	out << "#undef ULONG_MIN" << std::endl;
	out << "#undef ULONG_MAX" << std::endl;
	out << "#undef LLONG_MIN" << std::endl;
	out << "#undef LLONG_MAX" << std::endl;
	out << "#undef ULLONG_MIN" << std::endl;
	out << "#undef ULLONG_MAX" << std::endl;

	out << "" << std::endl;

	// TODO: Fix this to generate info without using the c++stdlib for platforms without this available.

	out << "#define CHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits<char>::is_signed << std::endl;

	out << "#define CHAR_ROUNDS "      << "0x" << std::hex << (int)std::numeric_limits<char>::round_style  << std::endl;
	out << "#define CHAR_RADIX_DIG "   << "0x" << std::hex << (int)std::numeric_limits<char>::digits       << std::endl;
	out << "#define CHAR_DIG "         << "0x" << std::hex << (int)std::numeric_limits<char>::digits10     << std::endl;
	out << "#define CHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits<char>::max_digits10 << std::endl;
	out << "#define CHAR_RADIX "       << "0x" << std::hex << (int)std::numeric_limits<char>::radix        << std::endl;
	out << "#define CHAR_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<char>::traps       << std::endl;

	out << "#define CHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<char>::min()) << std::endl;
	out << "#define CHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<char>::max()) << std::endl;

	out << "" << std::endl;

	out << "#define WCHAR_IS_SIGNED " << std::boolalpha << std::numeric_limits<wchar_t>::is_signed << std::endl;

	out << "#define WCHAR_ROUNDS "      << "0x" << std::hex << std::numeric_limits<wchar_t>::round_style  << std::endl;
	out << "#define WCHAR_RADIX_DIG "   << "0x" << std::hex << std::numeric_limits<wchar_t>::digits       << std::endl;
	out << "#define WCHAR_DIG "         << "0x" << std::hex << std::numeric_limits<wchar_t>::digits10     << std::endl;
	out << "#define WCHAR_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<wchar_t>::max_digits10 << std::endl;
	out << "#define WCHAR_RADIX "       << "0x" << std::hex << std::numeric_limits<wchar_t>::radix        << std::endl;
	out << "#define WCHAR_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<wchar_t>::traps  << std::endl;

	out << "#define WCHAR_MIN " << "0x" << std::hex << +std::numeric_limits<wchar_t>::min() << std::endl;
	out << "#define WCHAR_MAX " << "0x" << std::hex << +std::numeric_limits<wchar_t>::max() << std::endl;

	out << "" << std::endl;

	out << "#define SCHAR_ROUNDS "      << "0x" << std::hex << (int)std::numeric_limits<signed char>::round_style  << std::endl;
	out << "#define SCHAR_RADIX_DIG "   << "0x" << std::hex << (int)std::numeric_limits<signed char>::digits       << std::endl;
	out << "#define SCHAR_DIG "         << "0x" << std::hex << (int)std::numeric_limits<signed char>::digits10     << std::endl;
	out << "#define SCHAR_DECIMAL_DIG " << "0x" << std::hex << (int)std::numeric_limits<signed char>::max_digits10 << std::endl;
	out << "#define SCHAR_RADIX "       << "0x" << std::hex << (int)std::numeric_limits<signed char>::radix        << std::endl;
	out << "#define SCHAR_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<signed char>::traps       << std::endl;

	out << "#define SCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<signed char>::min()) << std::endl;
	out << "#define SCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<signed char>::max()) << std::endl;

	out << "" << std::endl;

	out << "#define UCHAR_ROUNDS "      << "0x" << std::hex << std::numeric_limits<unsigned char>::round_style  << std::endl;
	out << "#define UCHAR_RADIX_DIG "   << "0x" << std::hex << std::numeric_limits<unsigned char>::digits       << std::endl;
	out << "#define UCHAR_DIG "         << "0x" << std::hex << std::numeric_limits<unsigned char>::digits10     << std::endl;
	out << "#define UCHAR_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned char>::max_digits10 << std::endl;
	out << "#define UCHAR_RADIX "       << "0x" << std::hex << std::numeric_limits<unsigned char>::radix        << std::endl;
	out << "#define UCHAR_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<unsigned char>::traps                << std::endl;

	out << "#define UCHAR_MIN " << "0x" << std::hex << (0xFF & +std::numeric_limits<unsigned char>::min()) << std::endl;
	out << "#define UCHAR_MAX " << "0x" << std::hex << (0xFF & +std::numeric_limits<unsigned char>::max()) << std::endl;

	out << "" << std::endl;

	out << "#define SHORT_ROUNDS "      << "0x" << std::hex << std::numeric_limits<short>::round_style  << std::endl;
	out << "#define SHORT_RADIX_DIG "   << "0x" << std::hex << std::numeric_limits<short>::digits       << std::endl;
	out << "#define SHORT_DIG "         << "0x" << std::hex << std::numeric_limits<short>::digits10     << std::endl;
	out << "#define SHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<short>::max_digits10 << std::endl;
	out << "#define SHORT_RADIX "       << "0x" << std::hex << std::numeric_limits<short>::radix        << std::endl;
	out << "#define SHORT_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<short>::traps  << std::endl;

	out << "#define SHORT_MIN " << "0x" << std::hex << std::numeric_limits<short>::min() << std::endl;
	out << "#define SHORT_MAX " << "0x" << std::hex << std::numeric_limits<short>::max() << std::endl;

	out << "" << std::endl;

	out << "#define USHORT_ROUNDS "      << "0x" << std::hex << std::numeric_limits<unsigned short>::round_style  << std::endl;
	out << "#define USHORT_RADIX_DIG "   << "0x" << std::hex << std::numeric_limits<unsigned short>::digits       << std::endl;
	out << "#define USHORT_DIG "         << "0x" << std::hex << std::numeric_limits<unsigned short>::digits10     << std::endl;
	out << "#define USHORT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned short>::max_digits10 << std::endl;
	out << "#define USHORT_RADIX "       << "0x" << std::hex << std::numeric_limits<unsigned short>::radix        << std::endl;
	out << "#define USHORT_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<unsigned short>::traps  << std::endl;

	out << "#define USHORT_MIN " << "0x" << std::hex << std::numeric_limits<unsigned short>::min() << std::endl;
	out << "#define USHORT_MAX " << "0x" << std::hex << std::numeric_limits<unsigned short>::max() << std::endl;

	out << "" << std::endl;

	out << "#define INT_ROUNDS "      << "0x" << std::hex << std::numeric_limits<int>::round_style  << std::endl;
	out << "#define INT_RADIX_DIG "   << "0x" << std::hex << std::numeric_limits<int>::digits       << std::endl;
	out << "#define INT_DIG "         << "0x" << std::hex << std::numeric_limits<int>::digits10     << std::endl;
	out << "#define INT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<int>::max_digits10 << std::endl;
	out << "#define INT_RADIX "       << "0x" << std::hex << std::numeric_limits<int>::radix        << std::endl;
	out << "#define INT_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<int>::traps  << std::endl;

	out << "#define INT_MIN " << "0x" << std::hex << std::numeric_limits<int>::min() << std::endl;
	out << "#define INT_MAX " << "0x" << std::hex << std::numeric_limits<int>::max() << std::endl;

	out << "" << std::endl;

	out << "#define UINT_ROUNDS "      << "0x" << std::hex << std::numeric_limits<unsigned int>::round_style  << std::endl;
	out << "#define UINT_RADIX_DIG "   << "0x" << std::hex << std::numeric_limits<unsigned int>::digits       << std::endl;
	out << "#define UINT_DIG "         << "0x" << std::hex << std::numeric_limits<unsigned int>::digits10     << std::endl;
	out << "#define UINT_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned int>::max_digits10 << std::endl;
	out << "#define UINT_RADIX "       << "0x" << std::hex << std::numeric_limits<unsigned int>::radix        << std::endl;
	out << "#define UINT_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<unsigned int>::traps  << std::endl;

	out << "#define UINT_MIN " << "0x" << std::hex << std::numeric_limits<unsigned int>::min() << std::endl;
	out << "#define UINT_MAX " << "0x" << std::hex << std::numeric_limits<unsigned int>::max() << std::endl;

	out << "" << std::endl;

	out << "#define LONG_ROUNDS "      << "0x" << std::hex << std::numeric_limits<long int>::round_style  << std::endl;
	out << "#define LONG_RADIX_DIG "   << "0x" << std::hex << std::numeric_limits<long int>::digits       << std::endl;
	out << "#define LONG_DIG "         << "0x" << std::hex << std::numeric_limits<long int>::digits10     << std::endl;
	out << "#define LONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<long int>::max_digits10 << std::endl;
	out << "#define LONG_RADIX "       << "0x" << std::hex << std::numeric_limits<long int>::radix        << std::endl;
	out << "#define LONG_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<long int>::traps        << std::endl;

	out << "#define LONG_MIN " << "0x" << std::hex << std::numeric_limits<long int>::min() << std::endl;
	out << "#define LONG_MAX " << "0x" << std::hex << std::numeric_limits<long int>::max() << std::endl;

	out << "" << std::endl;

	out << "#define ULONG_ROUNDS "      << "0x" << std::hex << std::numeric_limits<unsigned long int>::round_style  << std::endl;
	out << "#define ULONG_RADIX_DIG "   << "0x" << std::hex << std::numeric_limits<unsigned long int>::digits       << std::endl;
	out << "#define ULONG_DIG "         << "0x" << std::hex << std::numeric_limits<unsigned long int>::digits10     << std::endl;
	out << "#define ULONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long int>::max_digits10 << std::endl;
	out << "#define ULONG_RADIX "       << "0x" << std::hex << std::numeric_limits<unsigned long int>::radix        << std::endl;
	out << "#define ULONG_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<unsigned long int>::traps  << std::endl;

	out << "#define ULONG_MIN " << "0x" << std::hex << std::numeric_limits<unsigned long int>::min() << std::endl;
	out << "#define ULONG_MAX " << "0x" << std::hex << std::numeric_limits<unsigned long int>::max() << std::endl;

	out << "" << std::endl;

	out << "#define LLONG_ROUNDS "      << "0x" << std::hex << std::numeric_limits<long long>::round_style  << std::endl;
	out << "#define LLONG_RADIX_DIG "   << "0x" << std::hex << std::numeric_limits<long long>::digits       << std::endl;
	out << "#define LLONG_DIG "         << "0x" << std::hex << std::numeric_limits<long long>::digits10     << std::endl;
	out << "#define LLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<long long>::max_digits10 << std::endl;
	out << "#define LLONG_RADIX "       << "0x" << std::hex << std::numeric_limits<long long>::radix        << std::endl;
	out << "#define LLONG_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<long long>::traps  << std::endl;

	out << "#define LLONG_MIN " << "0x" << std::hex << std::numeric_limits<long long>::min() << std::endl;
	out << "#define LLONG_MAX " << "0x" << std::hex << std::numeric_limits<long long>::max() << std::endl;

	out << "" << std::endl;

	out << "#define ULLONG_ROUNDS "      << "0x" << std::hex << std::numeric_limits<unsigned long long>::round_style  << std::endl;
	out << "#define ULLONG_RADIX_DIG "   << "0x" << std::hex << std::numeric_limits<unsigned long long>::digits       << std::endl;
	out << "#define ULLONG_DIG "         << "0x" << std::hex << std::numeric_limits<unsigned long long>::digits10     << std::endl;
	out << "#define ULLONG_DECIMAL_DIG " << "0x" << std::hex << std::numeric_limits<unsigned long long>::max_digits10 << std::endl;
	out << "#define ULLONG_RADIX "       << "0x" << std::hex << std::numeric_limits<unsigned long long>::radix        << std::endl;
	out << "#define ULLONG_TRAPS "       << "0x" << std::boolalpha << std::numeric_limits<unsigned long long>::traps  << std::endl;

	out << "#define ULLONG_MIN " << "0x" << std::hex << std::numeric_limits<unsigned long long>::min() << std::endl;
	out << "#define ULLONG_MAX " << "0x" << std::hex << std::numeric_limits<unsigned long long>::max() << std::endl;

	out << "" << std::endl;

	out << "#endif // FENNEC_LANG_INTEGER_H" << std::endl;

	out.close();

	return;
}

#endif // FENNEC_METAPROGRAMMING_INTEGER_H
