#include <Core/Common/NonNullPtr.h>
#include <Core/Logging/LogManager.h>
#include <Core/Logging/LogTypes.h>
#include <Graphics/D3D12/D3D12GraphicsDevice.h>
#include <Graphics/D3D12/D3D12Utils.h>

namespace Juliet::D3D12
{
    // From SDLGPU
    // TODO Do my own version.
    extern void LogError(NonNullPtr<ID3D12Device5> D3D12Device, const char* errorMessage, HRESULT result)
    {
#define MAX_ERROR_LEN 1024 // FIXME: Arbitrary!

        // Buffer for text, ensure space for \0 terminator after buffer
        char wszMsgBuff[MAX_ERROR_LEN + 1];
        // Number of chars returned.

        if (result == DXGI_ERROR_DEVICE_REMOVED)
        {
            result = D3D12Device->GetDeviceRemovedReason();
        }

        // Try to get the message from the system errors.
        DWORD dwChars = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
                                       static_cast<DWORD>(result), 0, wszMsgBuff, MAX_ERROR_LEN, nullptr);

        // No message? Screw it, just post the code.
        if (dwChars == 0)
        {
            Log(LogLevel::Error, LogCategory::Graphics, "%s! Error: " HRESULT_FMT, errorMessage, result);
            return;
        }

        // Ensure valid range
        dwChars = Min<DWORD>(dwChars, MAX_ERROR_LEN);

        // Trim whitespace from tail of message
        while (dwChars > 0)
        {
            if (wszMsgBuff[dwChars - 1] <= ' ')
            {
                dwChars--;
            }
            else
            {
                break;
            }
        }

        // Ensure null-terminated string
        wszMsgBuff[dwChars] = '\0';

        Log(LogLevel::Error, LogCategory::Graphics, "%s! Error: %s" HRESULT_FMT, errorMessage, wszMsgBuff, result);
    }
} // namespace Juliet::D3D12
