#include "get_last_error.hpp"

#ifdef _MSC_VER

    #include <type_traits>

    #include <QtDebug>
    #include <QtGlobal>

    #include <tchar.h>
    #include <windows.h>

    #include "log_tr.hpp"

namespace detail {

template<typename...>
struct always_false : std::false_type {
};

template<typename... Ts>
inline constexpr auto always_false_v = always_false<Ts...>::value;

template<typename T>
static QString fromTchar(T* tString)
{
    if constexpr(std::is_same_v<T, char>) {
        return QString().fromLocal8Bit(tString).trimmed();
    }
    else if constexpr(std::is_same_v<T, wchar_t>) {
        return QString().fromWCharArray(tString).trimmed();
    }
    else {
        static_assert(always_false_v<T>, "Unknown TCHAR type");
    }
}

} // namespace detail

QString getLastErrorString()
{
    DWORD lastErrorId = GetLastError();

    TCHAR* msgBuf = nullptr;
    const auto formatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;

    if(FormatMessage(formatFlags, nullptr, lastErrorId, 0, reinterpret_cast<LPTSTR>(&msgBuf), 0, nullptr) == 0) {
        return log_tr("FormatMessage failed with error code '%1' while formatting error message for code: %2").arg(GetLastError()).arg(lastErrorId);
    }

    const auto lastErrorString = detail::fromTchar(msgBuf);

    LocalFree(msgBuf);

    return lastErrorString;
}

#endif
