#pragma once

#include <Windows.h>
#include <shellscalingapi.h>

#include <string>

#include "renderer_gl/opengl_capabilities.h"

class App;

namespace pp::platform::windows {

bool win32_renderdoc_init();
void win32_renderdoc_frame_start();
void win32_renderdoc_frame_end();

extern HRESULT (*GetDpiForMonitor_fn)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);
extern HRESULT (*SetProcessDpiAwareness_fn)(PROCESS_DPI_AWARENESS value);

void init_shcore_API();
std::string GetLastErrorAsString();
void _pre_call_callback(const char* name, void* funcptr, int len_args, ...);
void _post_call_callback(const char* name, void* funcptr, int len_args, ...);
int read_WMI_info();

struct MainWindowStartupState
{
    WNDCLASS window_class{};
    PIXELFORMATDESCRIPTOR pixel_format{};
    DWORD window_style = WS_OVERLAPPEDWINDOW;
    RECT client_rect{ 0, 0, 0, 0 };
    POINT client_pos{ CW_USEDEFAULT, CW_USEDEFAULT };
    int show_command = SW_NORMAL;
};

struct OpenGlWindowContext
{
    HDC device_context{};
    HGLRC render_context{};
    pp::renderer::gl::OpenGlRuntimeInfo runtime_info{};
};

enum class MainStartupResult
{
    Ok = 0,
    GladLoadFailure = 1,
    MissingCoreContextSupport = 2,
};

void ensure_runtime_data_directory();
void setup_exception_handler(const App& app);
int run_winmain_entry(int (*entry_point)(int, char**));
MainWindowStartupState initialize_main_window_startup_state(App& app);
void create_main_window(const MainWindowStartupState& startup, HWND& hWnd, HINSTANCE hInst, const wchar_t* window_title);
void initialize_pixel_format_descriptor(PIXELFORMATDESCRIPTOR& pixel_format);
bool load_glad_entry_points(HDC device_context);
pp::renderer::gl::OpenGlRuntimeInfo log_runtime_info();
bool upgrade_to_core_gl_context(const MainWindowStartupState& startup, HWND& hWnd, HINSTANCE hInst, const wchar_t* window_title, OpenGlWindowContext& context);
MainStartupResult initialize_main_window_and_gl(MainWindowStartupState& startup, HWND& hWnd, HINSTANCE hInst, wchar_t* window_title, OpenGlWindowContext& context);

}
