#ifndef yc_magic_enum_H
#define yc_magic_enum_H
#include "magic_enum/magic_enum.hpp"
#include <iostream>
#include <sstream>

template <typename EnumType>
EnumType to_enum(const std::string& str) {
    auto opt = magic_enum::enum_cast<EnumType>(str);
    if (opt.has_value()) {
        return opt.value(); // 返回枚举值
    }
    std::cerr <<  std::string(magic_enum::enum_type_name<EnumType>()) +"  字符串转换枚举值错误！str:" + str + "\n";
    exit(-1);
}

template <typename EnumType>
std::optional<EnumType> to_enum2(const std::string& str) {
    auto opt = magic_enum::enum_cast<EnumType>(str);
    if (opt.has_value()) {
        return opt.value(); // 返回枚举值
    }
    return std::nullopt;
}

template <typename EnumType>
std::string to_string(EnumType type) {
    return std::string(magic_enum::enum_name(type));
}

template <typename EnumType>
std::optional<EnumType> int_to_enum(int enum_value) {
    // 静态断言，确保 EnumType 是枚举类型
    static_assert(std::is_enum_v<EnumType>, "EnumType must be an enum type");
    // 使用 magic_enum 获取所有的枚举值
    auto enum_values = magic_enum::enum_values<EnumType>();
    // 检查是否存在匹配的枚举值
    for (auto value : enum_values) {
        if (static_cast<int>(value) == enum_value) {
            return value;  // 返回匹配的枚举值
        }
    }
    // 如果没有匹配的枚举值，返回 std::nullopt
    return std::nullopt;
}

template <typename EnumType>
std::optional<std::string> enum_int_to_string(int enum_value) {
    auto tmp = int_to_enum<EnumType>(enum_value);
    if (!tmp.has_value()) return std::nullopt;
    return to_string(tmp.value());
}

template <typename Enum>
std::vector<Enum> split_flags(Enum flags)
{
    static_assert(std::is_enum_v<Enum>, "Template parameter must be an enum type");
    std::vector<Enum> setFlags;
    for (auto flag : magic_enum::enum_values<Enum>())
    {
        if ((flags & flag) == flag)
        {
            setFlags.push_back(flag);
        }
    }
    return setFlags;
}


inline std::string to_string(const char* val) {
    return std::string(val);
}

template <>
inline std::string to_string(std::string val) {
    return val;
}
template <>
inline std::string to_string(bool val) {
    return val ? "true" : "false";
}
template <>
inline std::string to_string(void* val) {
    std::ostringstream oss;
    oss << "0x" << std::hex << std::showbase << reinterpret_cast<std::uintptr_t>(val);
    return oss.str();
}

#define IMPL_to_string_from_std(Type) template <> \
inline std::string to_string(Type val) { \
    return std::to_string(val); \
} \

IMPL_to_string_from_std(signed char)
IMPL_to_string_from_std(short)
IMPL_to_string_from_std(int)
IMPL_to_string_from_std(long)
IMPL_to_string_from_std(long long)
IMPL_to_string_from_std(unsigned char)
IMPL_to_string_from_std(unsigned short)
IMPL_to_string_from_std(unsigned int)
IMPL_to_string_from_std(unsigned long)
IMPL_to_string_from_std(unsigned long long)
IMPL_to_string_from_std(float)
IMPL_to_string_from_std(double)
IMPL_to_string_from_std(long double)
#undef IMPL_to_string_from_std






#endif