from ctypes import POINTER as _P
from ._dll_loader import SDLFunc

from .sdlobjects import *

SDLFunc("SDL_SetMainReady")()

# -------- Init -------- #

def SDL_Init(s): return SDLFunc("SDL_Init", [c_uint32], c_int)(s)
def SDL_InitSubSystem(s): return SDLFunc("SDL_InitSubSystem", [c_uint32], c_int)(s)
def SDL_QuitSubSystem(s): return SDLFunc("SDL_QuitSubSystem", [c_uint32])(s)
def SDL_WasInit(s): return SDLFunc("SDL_WasInit", [c_uint32], c_uint32)(s)
def SDL_Quit(): return SDLFunc("SDL_Quit")()

# -------- Version -------- #

def SDL_GetVersion() -> SDL_version:
    version = SDL_version()
    SDLFunc("SDL_GetVersion", [_P(SDL_version)])(version)
    return version

def SDL_GetRevision() -> str: return SDLFunc("SDL_GetRevision", None, c_char_p)().decode()
def SDL_GetPlatform() -> str: return SDLFunc("SDL_GetPlatform", None, c_char_p)().decode()

# -------- Other -------- #

def SDL_LogMessage(priority: int, msg: str): SDLFunc("SDL_LogMessage", [c_int, c_int, c_char_p])(0, priority if 3 <= priority <= 6 else 3, msg.encode())
def SDL_RWFromFile(file: str, mode: str) -> SDL_RWops: return SDLFunc("SDL_RWFromFile", [c_char_p, c_char_p], _P(SDL_RWops))(file.encode(), mode.encode())
def SDL_RWFromMem(mem: bytes, size: int) -> SDL_RWops: return SDLFunc("SDL_RWFromMem", [c_char_p, c_int], _P(SDL_RWops))(mem, size)
def SDL_RWFromConstMem(mem: bytes, size: int) -> SDL_RWops: return SDLFunc("SDL_RWFromConstMem", [c_char_p, c_int], _P(SDL_RWops))(mem, size)
def SDL_RWclose(rw: SDL_RWops): SDLFunc("SDL_RWclose", [_P(SDL_RWops)], c_int)(rw)
def SDL_AllocRW() -> SDL_RWops: return SDLFunc("SDL_AllocRW", None, _P(SDL_RWops))()
def SDL_FreeRW(rw: SDL_RWops): SDLFunc("SDL_FreeRW", [_P(SDL_RWops)])(rw)
def SDL_GetPowerInfo():
    seconds, percent = c_int(), c_int()
    ret = SDLFunc("SDL_GetPowerInfo", [_P(c_int), _P(c_int)], SDL_PowerState)(byref(seconds), byref(percent))
    seconds, percent = seconds.value, percent.value
    return seconds if seconds >= 0 else None, percent if percent >= 0 else None, ret

def SDL_GetPreferredLocales() -> list[SDL_Locale]:
    locales = []
    loc_size = sizeof(SDL_Locale)
    p = SDLFunc("SDL_GetPreferredLocales", None, c_void_p)()
    while True:
        loc = cast(p, _P(SDL_Locale))
        if not loc or loc.contents.language is None:
            break
        locales.append(loc.contents)
        p = p + loc_size
    return locales

def SDL_SetClipboardText(text: str) -> bool: return bool(SDLFunc("SDL_SetClipboardText", [c_char_p], c_int)(text.encode()))
def SDL_GetClipboardText() -> str: return SDLFunc("SDL_GetClipboardText", None, c_char_p)().decode()
def SDL_HasClipboardText() -> bool: return bool(SDLFunc("SDL_HasClipboardText", None, SDL_bool)())
def SDL_SetPrimarySelectionText(text: str) -> bool: return bool(SDLFunc("SDL_SetPrimarySelectionText", [c_char_p], c_int)(text.encode()))
def SDL_GetPrimarySelectionText() -> str: return SDLFunc("SDL_GetPrimarySelectionText", None, c_char_p)().decode()
def SDL_HasPrimarySelectionText() -> bool: return bool(SDLFunc("SDL_HasPrimarySelectionText", None, SDL_bool)())
def SDL_OpenURL(url: str) -> bool: return bool(SDLFunc("SDL_OpenURL", [c_char_p], c_int)(url.encode()))

# -------- Audio -------- #

# -------- CpuInfo -------- #

def SDL_GetCPUCount(): return SDLFunc("SDL_GetCPUCount", None, c_int)()
def SDL_GetCPUCacheLineSize(): return SDLFunc("SDL_GetCPUCacheLineSize", None, c_int)()
def SDL_GetSystemRAM(): return SDLFunc("SDL_GetSystemRAM", None, c_int)()
def SDL_HasRDTSC(): return bool(SDLFunc("SDL_HasRDTSC", None, SDL_bool)())
def SDL_HasAltiVec(): return bool(SDLFunc("SDL_HasAltiVec", None, SDL_bool)())
def SDL_HasMMX(): return bool(SDLFunc("SDL_HasMMX", None, SDL_bool)())
def SDL_Has3DNow(): return bool(SDLFunc("SDL_Has3DNow", None, SDL_bool)())
def SDL_HasSSE(): return bool(SDLFunc("SDL_HasSSE", None, SDL_bool)())
def SDL_HasSSE2(): return bool(SDLFunc("SDL_HasSSE2", None, SDL_bool)())
def SDL_HasSSE3(): return bool(SDLFunc("SDL_HasSSE3", None, SDL_bool)())
def SDL_HasSSE41(): return bool(SDLFunc("SDL_HasSSE41", None, SDL_bool)())
def SDL_HasSSE42(): return bool(SDLFunc("SDL_HasSSE42", None, SDL_bool)())
def SDL_HasAVX(): return bool(SDLFunc("SDL_HasAVX", None, SDL_bool)())
def SDL_HasAVX2(): return bool(SDLFunc("SDL_HasAVX2", None, SDL_bool)())
def SDL_HasAVX512F(): return bool(SDLFunc("SDL_HasAVX512F", None, SDL_bool)())
def SDL_HasARMSIMD(): return bool(SDLFunc("SDL_HasARMSIMD", None, SDL_bool)())
def SDL_HasNEON(): return bool(SDLFunc("SDL_HasNEON", None, SDL_bool)())
def SDL_HasLSX(): return bool(SDLFunc("SDL_HasLSX", None, SDL_bool)())
def SDL_HasLASX(): return bool(SDLFunc("SDL_HasLASX", None, SDL_bool)())
def SDL_SIMDGetAlignment(): return SDLFunc("SDL_SIMDGetAlignment", None, c_size_t)()
def SDL_SIMDAlloc(size_len): return SDLFunc("SDL_SIMDAlloc", [c_size_t], c_void_p)(size_len)
def SDL_SIMDRealloc(mem, size_len): return SDLFunc("SDL_SIMDRealloc", [c_void_p, c_size_t], c_void_p)(mem, size_len)
def SDL_SIMDFree(ptr): return SDLFunc("SDL_SIMDFree", [c_void_p], None)(ptr)

# -------- Video -------- #

# -- Pixels -- #

def SDL_AllocFormat(pformat): return SDLFunc("SDL_AllocFormat", [c_uint32], _P(SDL_PixelFormat))(pformat)
def SDL_FreeFormat(pformat): SDLFunc("SDL_FreeFormat", [_P(SDL_PixelFormat)])(pformat)

# -- Surface -- #

def SDL_CreateRGBSurface(flags: int, width: int, height: int, depth: int, r: int, g: int, b: int, a: int) -> SDL_Surface: return SDLFunc("SDL_CreateRGBSurface", [c_uint32, c_int, c_int, c_int, c_uint32, c_uint32, c_uint32, c_uint32], _P(SDL_Surface))(flags, width, height, depth, r, g, b, a)
def SDL_CreateRGBSurfaceWithFormat(flags, width, height, depth, pformat): return SDLFunc("SDL_CreateRGBSurfaceWithFormat", [c_uint32, c_int, c_int, c_int, c_uint32], _P(SDL_Surface))(flags, width, height, depth, pformat)
def SDL_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, rmask, gmask, bmask, amask): return SDLFunc("SDL_CreateRGBSurfaceFrom", [c_void_p, c_int, c_int, c_int, c_int, c_uint32, c_uint32, c_uint32, c_uint32], _P(SDL_Surface))(pixels, width, height, depth, pitch, rmask, gmask, bmask, amask)
def SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, depth, pitch, pformat): return SDLFunc("SDL_CreateRGBSurfaceWithFormatFrom", [c_void_p, c_int, c_int, c_int, c_int, c_uint32], _P(SDL_Surface))(pixels, width, height, depth, pitch, pformat)
def SDL_SetSurfaceColorMod(surface, r, g, b): return SDLFunc("SDL_SetSurfaceColorMod", [_P(SDL_Surface), c_uint8, c_uint8, c_uint8], c_int)(surface, r, g, b)
def SDL_GetSurfaceColorMod(surface, r, g, b): return SDLFunc("SDL_GetSurfaceColorMod", [_P(SDL_Surface), _P(c_uint8), _P(c_uint8), _P(c_uint8)], c_int)(surface, r, g, b)
def SDL_SetSurfaceAlphaMod(surface, alpha): return SDLFunc("SDL_SetSurfaceAlphaMod", [_P(SDL_Surface), c_uint8], c_int)(surface, alpha)
def SDL_GetSurfaceAlphaMod(surface, alpha): return SDLFunc("SDL_GetSurfaceAlphaMod", [_P(SDL_Surface), _P(c_uint8)], c_int)(surface, alpha)
def SDL_MapRGB(pformat, r, g, b): return SDLFunc("SDL_MapRGB", [_P(SDL_PixelFormat), c_uint8, c_uint8, c_uint8], c_uint32)(pformat, r, g, b)
def SDL_MapRGBA(pformat, r, g, b, a): return SDLFunc("SDL_MapRGBA", [_P(SDL_PixelFormat), c_uint8, c_uint8, c_uint8, c_uint8], c_uint32)(pformat, r, g, b, a)
def SDL_FreeSurface(surface): SDLFunc("SDL_FreeSurface", [_P(SDL_Surface)])(surface)
def SDL_DuplicateSurface(surface): return SDLFunc("SDL_DuplicateSurface", [_P(SDL_Surface)], _P(SDL_Surface))(surface)
def SDL_ConvertSurface(src, fmt, flags): return SDLFunc("SDL_ConvertSurface", [_P(SDL_Surface), _P(SDL_PixelFormat), c_uint32], _P(SDL_Surface))(src, fmt, flags)
def SDL_ConvertSurfaceFormat(src, pixel_format, flags): return SDLFunc("SDL_ConvertSurfaceFormat", [_P(SDL_Surface), c_uint32, c_uint32], _P(SDL_Surface))(src, pixel_format, flags)
def SDL_FillRect(surface, rect, color): return SDLFunc("SDL_FillRect", [_P(SDL_Surface), _P(SDL_Rect), c_uint32], c_int)(surface, rect, color)
def SDL_UpperBlit(src, srcrect, dst, dstrect): return SDLFunc("SDL_UpperBlit", [_P(SDL_Surface), _P(SDL_Rect), _P(SDL_Surface), _P(SDL_Rect)], returns=c_int)(src, srcrect, dst, dstrect)
def SDL_BlitSurface(src, srcrect, dst, dstrect): return SDL_UpperBlit(src, srcrect, dst, dstrect)
def SDL_UpperBlitScaled(src, srcrect, dst, dstrect): return SDLFunc("SDL_UpperBlitScaled", [_P(SDL_Surface), _P(SDL_Rect), _P(SDL_Surface), _P(SDL_Rect)], returns=c_int)(src, srcrect, dst, dstrect)
def SDL_BlitScaled(src, srcrect, dst, dstrect): return SDL_UpperBlitScaled(src, srcrect, dst, dstrect)
def SDL_LockSurface(surface): return SDLFunc("SDL_LockSurface", [_P(SDL_Surface)], c_int)(surface)

# -- Window -- #

def SDL_CreateShapedWindow(title, x, y, w, h, flags): return SDLFunc("SDL_CreateShapedWindow", [c_char_p, c_uint, c_uint, c_uint, c_uint, c_uint32], returns=_P(SDL_Window))(title, x, y, w, h, flags)
def SDL_IsShapedWindow(window): return SDLFunc("SDL_IsShapedWindow", [_P(SDL_Window)], SDL_bool)(window)
def SDL_SetWindowShape(window, shape, shape_mode): return SDLFunc("SDL_SetWindowShape", [_P(SDL_Window), _P(SDL_Surface), _P(SDL_WindowShapeMode)], returns=c_int)(window, shape, shape_mode)
def SDL_GetShapedWindowMode(window, shape_mode): return SDLFunc("SDL_GetShapedWindowMode", [_P(SDL_Window), _P(SDL_WindowShapeMode)], c_int)(window, shape_mode)
def SDL_GetNumVideoDrivers(): return SDLFunc("SDL_GetNumVideoDrivers", None, c_int)()
def SDL_GetVideoDriver(index): return SDLFunc("SDL_GetVideoDriver", [c_int], c_char_p)(index)
def SDL_VideoInit(driver_name: str = None): return SDLFunc("SDL_VideoInit", [c_char_p], c_int)(driver_name)
def SDL_VideoQuit(): SDLFunc("SDL_VideoQuit")()
def SDL_GetCurrentVideoDriver(): return SDLFunc("SDL_GetCurrentVideoDriver", None, c_char_p)()
def SDL_GetNumVideoDisplays() -> int: return SDLFunc("SDL_GetNumVideoDisplays", None, c_int)()

def SDL_GetDisplayName(display_index: int) -> str | None:
    ret = SDLFunc("SDL_GetDisplayName", [c_int], c_char_p)(display_index)
    if isinstance(ret, bytes):
        return ret.decode()
    return ret

def SDL_GetDisplayBounds(display_index, rect): return SDLFunc("SDL_GetDisplayBounds", [c_int, _P(SDL_Rect)], c_int)(display_index, rect)
def SDL_GetDisplayUsableBounds(display_index, rect): return SDLFunc("SDL_GetDisplayUsableBounds", [c_int, _P(SDL_Rect)], c_int)(display_index, rect)
def SDL_GetDisplayDPI(display_index, ddpi, hdpi, vdpi): return SDLFunc("SDL_GetDisplayDPI", [c_int, _P(c_float), _P(c_float), _P(c_float)], returns=c_int)(display_index, ddpi, hdpi, vdpi)
def SDL_GetDisplayOrientation(display_index): return SDLFunc("SDL_GetDisplayOrientation", [c_int], SDL_DisplayOrientation)(display_index)
def SDL_GetNumDisplayModes(display_index): return SDLFunc("SDL_GetNumDisplayModes", [c_int], c_int)(display_index)
def SDL_GetDisplayMode(display_index, mode_index, mode): return SDLFunc("SDL_GetDisplayMode", [c_int, c_int, _P(SDL_DisplayMode)], c_int)(display_index, mode_index, mode)
def SDL_GetDesktopDisplayMode(display_index, mode): return SDLFunc("SDL_GetDesktopDisplayMode", [c_int, _P(SDL_DisplayMode)], c_int)(display_index, mode)

def SDL_GetCurrentDisplayMode(display_index: int, mode: SDL_DisplayMode | None = None) -> int | SDL_DisplayMode:
    if mode is None:
        mode = SDL_DisplayMode()
    er = SDLFunc("SDL_GetCurrentDisplayMode", [c_int, _P(SDL_DisplayMode)], c_int)(display_index, mode)
    return er if er < 0 else mode

def SDL_GetClosestDisplayMode(display_index, mode, closest): return SDLFunc("SDL_GetClosestDisplayMode", [c_int, _P(SDL_DisplayMode), _P(SDL_DisplayMode)], returns=_P(SDL_DisplayMode))(display_index, mode, closest)
def SDL_GetPointDisplayIndex(point): return SDLFunc("SDL_GetPointDisplayIndex", [_P(SDL_Point)], c_int)(point)
def SDL_GetRectDisplayIndex(rect): return SDLFunc("SDL_GetRectDisplayIndex", [_P(SDL_Rect)], c_int)(rect)
def SDL_GetWindowDisplayIndex(window): return SDLFunc("SDL_GetWindowDisplayIndex", [_P(SDL_Window)], c_int)(window)
def SDL_SetWindowDisplayMode(window, mode): return SDLFunc("SDL_SetWindowDisplayMode", [_P(SDL_Window), _P(SDL_DisplayMode)], c_int)(window, mode)
def SDL_GetWindowDisplayMode(window, mode): return SDLFunc("SDL_GetWindowDisplayMode", [_P(SDL_Window), _P(SDL_DisplayMode)], c_int)(window, mode)
def SDL_CreateWindow(title: str, x: int, y: int, w: int, h: int, flags: int) -> SDL_Window | None: return SDLFunc("SDL_CreateWindow", [c_char_p, c_int, c_int, c_int, c_int, c_uint32], _P(SDL_Window))(title.encode() if type(title) == str else title, x, y, w, h, flags)
def SDL_GetWindowID(window: SDL_Window) -> int: return SDLFunc("SDL_GetWindowID", [_P(SDL_Window)], c_uint32)(window)
def SDL_GetWindowFromID(window_id: int) -> SDL_Window: return SDLFunc("SDL_GetWindowFromID", [c_uint32], _P(SDL_Window))(window_id)
def SDL_GetWindowFlags(window: SDL_Window) -> int: return SDLFunc("SDL_GetWindowFlags", [_P(SDL_Window)], c_uint32)(window)
def SDL_SetWindowTitle(window: SDL_Window, title: str): SDLFunc("SDL_SetWindowTitle", [_P(SDL_Window), c_char_p])(window, title.encode() if type(title) == str else title)
def SDL_GetWindowTitle(window: SDL_Window) -> str: return SDLFunc("SDL_GetWindowTitle", [_P(SDL_Window)], c_char_p)(window).decode()
def SDL_SetWindowIcon(window, surface): SDLFunc("SDL_SetWindowIcon", [_P(SDL_Window), _P(SDL_Surface)])(window, surface)
def SDL_SetWindowData(window: SDL_Window, name: str, data) -> any: return SDLFunc("SDL_SetWindowData", [_P(SDL_Window), c_char_p, _P(py_object)], _P(py_object))(window, name.encode(), data)
def SDL_GetWindowData(window: SDL_Window, name: str) -> any: return SDLFunc("SDL_GetWindowData", [_P(SDL_Window), c_char_p], _P(py_object))(window, name.encode())
def SDL_SetWindowPosition(window, x, y): SDLFunc("SDL_SetWindowPosition", [_P(SDL_Window), c_int, c_int])(window, x, y)

def SDL_GetWindowPosition(window):
    x, y = c_int(), c_int()
    SDLFunc("SDL_GetWindowPosition", [_P(SDL_Window), _P(c_int), _P(c_int)])(window, x, y)
    return x.value, y.value

def SDL_SetWindowSize(window, w, h): SDLFunc("SDL_SetWindowSize", [_P(SDL_Window), c_int, c_int])(window, w, h)

def SDL_GetWindowSize(window: SDL_Window):
    w, h = c_int(), c_int()
    SDLFunc("SDL_GetWindowSize", [_P(SDL_Window), _P(c_int), _P(c_int)])(window, w, h)
    return w.value, h.value

def SDL_SetWindowMinimumSize(window, min_w, min_h): SDLFunc("SDL_SetWindowMinimumSize", [_P(SDL_Window), c_int, c_int])(window, min_w, min_h)

def SDL_GetWindowMinimumSize(window):
    w, h = c_int(), c_int()
    SDLFunc("SDL_GetWindowMinimumSize", [_P(SDL_Window), _P(c_int), _P(c_int)])(window, w, h)
    return w.value, h.value

def SDL_SetWindowMaximumSize(window, max_w, max_h): SDLFunc("SDL_SetWindowMaximumSize", [_P(SDL_Window), c_int, c_int])(window, max_w, max_h)

def SDL_GetWindowMaximumSize(window):
    w, h = c_int(), c_int()
    SDLFunc("SDL_GetWindowMaximumSize", [_P(SDL_Window), _P(c_int), _P(c_int)])(window, w, h)
    return w.value, h.value

def SDL_SetWindowBordered(window, bordered): SDLFunc("SDL_SetWindowBordered", [_P(SDL_Window), SDL_bool])(window, bordered)
def SDL_SetWindowResizable(window, resizable): SDLFunc("SDL_SetWindowResizable", [_P(SDL_Window), SDL_bool])(window, resizable)
def SDL_SetWindowAlwaysOnTop(window, on_top): SDLFunc("SDL_SetWindowAlwaysOnTop", [_P(SDL_Window), SDL_bool])(window, on_top)
def SDL_SetWindowFullscreen(window, flags): return SDLFunc("SDL_SetWindowFullscreen", [_P(SDL_Window), c_uint32], c_int)(window, flags)
def SDL_ShowWindow(window): SDLFunc("SDL_ShowWindow", [_P(SDL_Window)])(window)
def SDL_HideWindow(window): SDLFunc("SDL_HideWindow", [_P(SDL_Window)])(window)
def SDL_RaiseWindow(window): SDLFunc("SDL_RaiseWindow", [_P(SDL_Window)])(window)
def SDL_MaximizeWindow(window): SDLFunc("SDL_MaximizeWindow", [_P(SDL_Window)])(window)
def SDL_MinimizeWindow(window): SDLFunc("SDL_MinimizeWindow", [_P(SDL_Window)])(window)
def SDL_RestoreWindow(window): SDLFunc("SDL_RestoreWindow", [_P(SDL_Window)])(window)

def SDL_GetWindowOpacity(window: SDL_Window):
    opacity = c_float()
    SDLFunc("SDL_GetWindowOpacity", [_P(SDL_Window), _P(c_float)], c_int)(window, opacity)
    return opacity.value

def SDL_SetWindowOpacity(window, opacity): return SDLFunc("SDL_SetWindowOpacity", [_P(SDL_Window), c_float], c_int)(window, opacity)
def SDL_GetWindowSurface(window): return SDLFunc("SDL_GetWindowSurface", [_P(SDL_Window)], _P(SDL_Surface))(window)
def SDL_SetWindowInputFocus(window): return SDLFunc("SDL_SetWindowInputFocus", [_P(SDL_Window)], c_int)(window)
def SDL_FlashWindow(window, operation): return SDLFunc("SDL_FlashWindow", [_P(SDL_Window), SDL_FlashOperation], c_int)(window, operation)
def SDL_DestroyWindow(window): SDLFunc("SDL_DestroyWindow", [_P(SDL_Window)])(window)
def SDL_IsScreenSaverEnabled(): return SDLFunc("SDL_IsScreenSaverEnabled", None, SDL_bool)()
def SDL_EnableScreenSaver(): SDLFunc("SDL_EnableScreenSaver")()
def SDL_DisableScreenSaver(): SDLFunc("SDL_DisableScreenSaver")()
def SDL_GetWindowWMInfo(window, info): return SDLFunc("SDL_GetWindowWMInfo", [_P(SDL_Window), _P(SDL_SysWMinfo)], SDL_bool)(window, info)
def SDL_GL_LoadLibrary(path): return SDLFunc("SDL_GL_LoadLibrary", [c_char_p], c_int)(path)
def SDL_GL_GetProcAddress(proc): return SDLFunc("SDL_GL_GetProcAddress", [c_char_p], c_void_p)(proc)
def SDL_GL_UnloadLibrary(): SDLFunc("SDL_GL_UnloadLibrary")()
def SDL_GL_ExtensionSupported(extension): return SDLFunc("SDL_GL_ExtensionSupported", [c_char_p], SDL_bool)(extension)
def SDL_GL_ResetAttributes(): SDLFunc("SDL_GL_ResetAttributes")()
def SDL_GL_SetAttribute(attr, value): return SDLFunc("SDL_GL_SetAttribute", [SDL_GLattr, c_int], c_int)(attr, value)
def SDL_GL_GetAttribute(attr, value): return SDLFunc("SDL_GL_GetAttribute", [SDL_GLattr, _P(c_int)], c_int)(attr, value)
def SDL_GL_CreateContext(window): return SDLFunc("SDL_GL_CreateContext", [_P(SDL_Window)], SDL_GLContext)(window)
def SDL_GL_MakeCurrent(window, context): return SDLFunc("SDL_GL_MakeCurrent", [_P(SDL_Window), SDL_GLContext], c_int)(window, context)
def SDL_GL_GetCurrentWindow(): return SDLFunc("SDL_GL_GetCurrentWindow", None, _P(SDL_Window))()
def SDL_GL_GetCurrentContext(): return SDLFunc("SDL_GL_GetCurrentContext", None, SDL_GLContext)()
def SDL_GL_GetDrawableSize(window):
    w, h = c_int(), c_int()
    SDLFunc("SDL_GL_GetDrawableSize", [_P(SDL_Window), _P(c_int), _P(c_int)])(window, w, h)
    return w.value, h.value

def SDL_GL_SetSwapInterval(interval): return SDLFunc("SDL_GL_SetSwapInterval", [c_int], c_int)(interval)
def SDL_GL_GetSwapInterval(): return SDLFunc("SDL_GL_GetSwapInterval", None, c_int)()
def SDL_GL_SwapWindow(window): SDLFunc("SDL_GL_SwapWindow", [_P(SDL_Window)])(window)
def SDL_GL_DeleteContext(context): SDLFunc("SDL_GL_DeleteContext", [SDL_GLContext])(context)

# -- Render -- #

def SDL_GetNumRenderDrivers(): return SDLFunc("SDL_GetNumRenderDrivers", None, c_int)()
def SDL_GetRenderDriverInfo(index, info): return SDLFunc("SDL_GetRenderDriverInfo", [c_int, _P(SDL_RendererInfo)], c_int)(index, info)

# review this function
def SDL_CreateWindowAndRenderer(width, height, window_flags):
    window, renderer = SDL_Window, SDL_Renderer
    SDLFunc("SDL_CreateWindowAndRenderer", [c_int, c_int, c_uint32, _P(_P(SDL_Window)), _P(_P(SDL_Renderer))], returns=c_int)(width, height, window_flags, window, renderer)
    return window, renderer

def SDL_CreateRenderer(window, index, flags) -> SDL_Renderer: return SDLFunc("SDL_CreateRenderer", [_P(SDL_Window), c_int, c_uint32], _P(SDL_Renderer))(window, index, flags)
def SDL_CreateSoftwareRenderer(surf: SDL_Surface) -> SDL_Renderer: return SDLFunc("SDL_CreateSoftwareRenderer", [_P(SDL_Surface)], _P(SDL_Renderer))(surf)
def SDL_GetRenderer(window) -> SDL_Renderer: return SDLFunc("SDL_GetRenderer", [_P(SDL_Window)], _P(SDL_Renderer))(window)
def SDL_RenderGetWindow(render) -> SDL_Window: return SDLFunc("SDL_RenderGetWindow", [_P(SDL_Renderer)], _P(SDL_Window))(render)
def SDL_SetRenderTarget(render: SDL_Renderer, texture: SDL_Texture | None) -> int: return SDLFunc("SDL_SetRenderTarget", [_P(SDL_Renderer), _P(SDL_Texture)], c_int)(render, texture)
def SDL_GetRenderTarget(render: SDL_Renderer) -> SDL_Texture: return SDLFunc("SDL_GetRenderTarget", [_P(SDL_Renderer)], _P(SDL_Texture))(render)
def SDL_GetRendererInfo(renderer, info): return SDLFunc("SDL_GetRendererInfo", [_P(SDL_Renderer), _P(SDL_RendererInfo)], c_int)(renderer, info)
def SDL_GetRendererOutputSize(renderer, w, h): return SDLFunc("SDL_GetRendererOutputSize", [_P(SDL_Renderer), _P(c_int), _P(c_int)], c_int)(renderer, w, h)
def SDL_CreateTexture(renderer, sformat, access, w, h): return SDLFunc("SDL_CreateTexture", [_P(SDL_Renderer), c_uint32, c_int, c_int, c_int], _P(SDL_Texture))(renderer, sformat, access, w, h)
def SDL_CreateTextureFromSurface(renderer, surface): return SDLFunc("SDL_CreateTextureFromSurface", [_P(SDL_Renderer), _P(SDL_Surface)], _P(SDL_Texture))(renderer, surface)

def SDL_QueryTexture(texture: SDL_Texture):
    flags = c_uint32()
    access, w, h = (c_int(), c_int(), c_int())
    ret = SDLFunc("SDL_QueryTexture", [_P(SDL_Texture), _P(c_uint32), _P(c_int), _P(c_int), _P(c_int)], returns=c_int)(texture, byref(flags), byref(access), byref(w), byref(h))
    if ret < 0:
        return None
    return flags.value, access.value, w.value, h.value

def SDL_SetTextureColorMod(texture, r, g, b): return SDLFunc("SDL_SetTextureColorMod", [_P(SDL_Texture), c_uint8, c_uint8, c_uint8], c_int)(texture, r, g, b)
def SDL_GetTextureColorMod(texture, r, g, b): return SDLFunc("SDL_GetTextureColorMod", [_P(SDL_Texture), _P(c_uint8), _P(c_uint8), _P(c_uint8)], c_int)(texture, r, g, b)
def SDL_SetTextureAlphaMod(texture, alpha): return SDLFunc("SDL_SetTextureAlphaMod", [_P(SDL_Texture), c_uint8], c_int)(texture, alpha)
def SDL_GetTextureAlphaMod(texture, alpha): return SDLFunc("SDL_GetTextureAlphaMod", [_P(SDL_Texture), _P(c_uint8)], c_int)(texture, alpha)
def SDL_SetTextureScaleMode(texture, scale_mode): return SDLFunc("SDL_SetTextureScaleMode", [_P(SDL_Texture), SDL_ScaleMode], returns=c_int)(texture, scale_mode)
def SDL_GetTextureScaleMode(texture, scale_mode): return SDLFunc("SDL_GetTextureScaleMode", [_P(SDL_Texture), _P(SDL_ScaleMode)], returns=c_int)(texture, scale_mode)
def SDL_UpdateTexture(texture, rect, pixels, pitch): return SDLFunc("SDL_UpdateTexture", [_P(SDL_Texture), _P(SDL_Rect), c_void_p, c_int], c_int)(texture, rect, pixels, pitch)
def SDL_UpdateYUVTexture(texture, rect, yplane, ypitch, uplane, upitch, vplane, vpitch): return SDLFunc("SDL_UpdateYUVTexture", [_P(SDL_Texture), _P(SDL_Rect), _P(c_uint8), c_int, _P(c_uint8), c_int, _P(c_uint8), c_int], returns=c_int)(texture, rect, yplane, ypitch, uplane, upitch, vplane, vpitch)
def SDL_UpdateNVTexture(texture, rect, yplane, ypitch, uvplane, uvpitch): return SDLFunc("SDL_UpdateNVTexture", [_P(SDL_Texture), _P(SDL_Rect), _P(c_uint8), c_int, _P(c_uint8), c_int], returns=c_int)(texture, rect, yplane, ypitch, uvplane, uvpitch)
def SDL_RenderSetLogicalSize(renderer, w, h): return SDLFunc("SDL_RenderSetLogicalSize", [_P(SDL_Renderer), c_int, c_int], c_int)(renderer, w, h)
def SDL_RenderGetLogicalSize(renderer, w, h): SDLFunc("SDL_RenderGetLogicalSize", [_P(SDL_Renderer), _P(c_int), _P(c_int)])(renderer, w, h)
def SDL_RenderSetViewport(renderer, rect): return SDLFunc("SDL_RenderSetViewport", [_P(SDL_Renderer), _P(SDL_Rect)], c_int)(renderer, rect)
def SDL_RenderGetViewport(renderer, rect): SDLFunc("SDL_RenderGetViewport", [_P(SDL_Renderer), _P(SDL_Rect)])(renderer, rect)
def SDL_RenderSetScale(renderer, x, y): return SDLFunc("SDL_RenderSetScale", [_P(SDL_Renderer), c_float, c_float], c_int)(renderer, x, y)
def SDL_RenderGetScale(renderer, x, y): SDLFunc("SDL_RenderGetScale", [_P(SDL_Renderer), _P(c_float), _P(c_float)])(renderer, x, y)
def SDL_SetRenderDrawColor(renderer, r, g, b, a): return SDLFunc("SDL_SetRenderDrawColor", [_P(SDL_Renderer), c_uint8, c_uint8, c_uint8, c_uint8], c_int)(renderer, r, g, b, a)

def SDL_GetRenderDrawColor(renderer):
    r, g, b, a = c_uint8(0), c_uint8(0), c_uint8(0), c_uint8(0)
    ret = SDLFunc("SDL_GetRenderDrawColor", [_P(SDL_Renderer), _P(c_uint8), _P(c_uint8), _P(c_uint8), _P(c_uint8)], returns=c_int)(renderer, byref(r), byref(g), byref(b), byref(a))
    if ret is None:
        return ret
    return r.value, g.value, b.value, a.value

def SDL_RenderReadPixels(renderer, rect, rformat, pixels, pitch): return SDLFunc("SDL_RenderReadPixels", [_P(SDL_Renderer), _P(SDL_Rect), c_uint32, c_void_p, c_int], returns=c_int)(renderer, rect, rformat, pixels, pitch)
def SDL_RenderClear(renderer): return SDLFunc("SDL_RenderClear", [_P(SDL_Renderer)], c_int)(renderer)
def SDL_RenderCopy(renderer, texture, srcrect, dstrect): return SDLFunc("SDL_RenderCopy", [_P(SDL_Renderer), _P(SDL_Texture), _P(SDL_Rect), _P(SDL_Rect)], returns=c_int)(renderer, texture, srcrect, dstrect)
def SDL_RenderCopyExF(renderer, texture, srcrect, dstrect, angle, center, flip): return SDLFunc("SDL_RenderCopyExF", args=[_P(SDL_Renderer), _P(SDL_Texture), _P(SDL_Rect), _P(SDL_FRect), c_double, _P(SDL_FPoint), SDL_RendererFlip], returns=c_int)(renderer, texture, srcrect, dstrect, angle, center, flip)
def SDL_RenderPresent(renderer): SDLFunc("SDL_RenderPresent", [_P(SDL_Renderer)])(renderer)
def SDL_DestroyTexture(texture): SDLFunc("SDL_DestroyTexture", [_P(SDL_Texture)])(texture)
def SDL_DestroyRenderer(renderer): SDLFunc("SDL_DestroyRenderer", [_P(SDL_Renderer)])(renderer)
def SDL_RenderSetVSync(renderer, vsync): return SDLFunc("SDL_RenderSetVSync", [_P(SDL_Renderer), c_int], c_int)(renderer, vsync)

# -------- MessageBox -------- #

def SDL_ShowMessageBox(messageboxdata, buttonid): return SDLFunc("SDL_ShowMessageBox", [_P(SDL_MessageBoxData), _P(c_int)], c_int)(messageboxdata, buttonid)
def SDL_ShowSimpleMessageBox(flags: int, title: str, msg: str): return SDLFunc("SDL_ShowSimpleMessageBox", [c_uint32, c_char_p, c_char_p, c_char_p], c_int)(flags, title.encode(), msg.encode(), None)

# -------- Events -------- #

# -- Touch -- #

def SDL_GetNumTouchDevices(): return SDLFunc("SDL_GetNumTouchDevices", None, c_int)()
def SDL_GetTouchDevice(index): return SDLFunc("SDL_GetTouchDevice", [c_int], SDL_TouchID)(index)
def SDL_GetTouchName(index): return SDLFunc("SDL_GetTouchName", [c_int], c_char_p)(index)
def SDL_GetTouchDeviceType(touch_id): return SDLFunc("SDL_GetTouchDeviceType", [SDL_TouchID], SDL_TouchDeviceType)(touch_id)
def SDL_GetNumTouchFingers(touch_id): return SDLFunc("SDL_GetNumTouchFingers", [SDL_TouchID], c_int)(touch_id)
def SDL_GetTouchFinger(touch_id, index): return SDLFunc("SDL_GetTouchFinger", [SDL_TouchID, c_int], _P(SDL_Finger))(touch_id, index)
def SDL_RecordGesture(touch_id): return SDLFunc("SDL_RecordGesture", [SDL_TouchID], c_int)(touch_id)
def SDL_SaveAllDollarTemplates(dst): return SDLFunc("SDL_SaveAllDollarTemplates", [_P(SDL_RWops)], c_int)(dst)
def SDL_SaveDollarTemplate(gesture_id, dst): return SDLFunc("SDL_SaveDollarTemplate", [SDL_GestureID, _P(SDL_RWops)], c_int)(gesture_id, dst)
def SDL_LoadDollarTemplates(touch_id, src): return SDLFunc("SDL_LoadDollarTemplates", [SDL_TouchID, _P(SDL_RWops)], c_int)(touch_id, src)

# -- Keyboard -- #

def SDL_GetKeyboardFocus(): return SDLFunc("SDL_GetKeyboardFocus", None, _P(SDL_Window))()
def SDL_GetKeyboardState(numkeys): return SDLFunc("SDL_GetKeyboardState", [_P(c_int)], _P(c_uint8))(numkeys)
def SDL_GetScancodeName(scancode): return SDLFunc("SDL_GetScancodeName", [SDL_Scancode], c_char_p)(scancode)
def SDL_GetScancodeFromName(name): return SDLFunc("SDL_GetScancodeFromName", [c_char_p], SDL_Scancode)(name)
def SDL_GetKeyName(key): return SDLFunc("SDL_GetKeyName", [SDL_Keycode], c_char_p)(key)
def SDL_GetKeyFromName(name): return SDLFunc("SDL_GetKeyFromName", [c_char_p], SDL_Keycode)(name)
def SDL_IsTextInputShown(): return bool(SDLFunc("SDL_IsTextInputShown", None, SDL_bool)())
def SDL_SetTextInputRect(rect): SDLFunc("SDL_SetTextInputRect", [_P(SDL_Rect)])(rect)

# -- Mouse -- #

def SDL_GetMouseState():
    x, y = c_int(0), c_int(0)
    mask = SDLFunc("SDL_GetMouseState", [_P(c_int), _P(c_int)], c_uint32)(byref(x), byref(y))
    return [[x.value, y.value], [(mask & (1 << i)) != 0 for i in range(5)]]

def SDL_GetMousePosition():
    xy, _ = SDL_GetMouseState()
    return xy

def SDL_GetMouseButtons():
    _, buttons = SDL_GetMouseState()
    return buttons

def SDL_GetRelativeMouseState():
    x, y = c_int(0), c_int(0)
    mask = SDLFunc("SDL_GetRelativeMouseState", [_P(c_int), _P(c_int)], c_uint32)(byref(x), byref(y))
    return [[x.value, y.value], [(mask & (1 << i)) != 0 for i in range(5)]]

def SDL_GetRelativeMousePosition():
    xy, _ = SDL_GetRelativeMouseState()
    return xy

def SDL_GetRelativeMouseButtons():
    _, buttons = SDL_GetRelativeMouseState()
    return buttons

def SDL_GetGlobalMouseState():
    x, y = c_int(0), c_int(0)
    mask = SDLFunc("SDL_GetGlobalMouseState", [_P(c_int), _P(c_int)], c_uint32)(byref(x), byref(y))
    return [[x.value, y.value], [(mask & (1 << i)) != 0 for i in range(5)]]

def SDL_GetGlobalMousePosition():
    xy, _ = SDL_GetGlobalMouseState()
    return xy

def SDL_GetGlobalMouseButtons():
    _, buttons = SDL_GetGlobalMouseState()
    return buttons

def SDL_GetMouseFocus(): return SDLFunc("SDL_GetMouseFocus", None, _P(SDL_Window))()
def SDL_WarpMouseInWindow(window: SDL_Window | None, x: int, y: int): SDLFunc("SDL_WarpMouseInWindow", [_P(SDL_Window), c_int, c_int])(window, x, y)
def SDL_WarpMouseGlobal(x, y): return SDLFunc("SDL_WarpMouseGlobal", [c_int, c_int], c_int)(x, y)
def SDL_SetRelativeMouseMode(enabled: bool): return SDLFunc("SDL_SetRelativeMouseMode", [SDL_bool], c_int)(int(enabled))
def SDL_GetRelativeMouseMode(): return bool(SDLFunc("SDL_GetRelativeMouseMode", None, SDL_bool)())
def SDL_CreateCursor(data, mask, w, h, hot_x, hot_y): return SDLFunc("SDL_CreateCursor", [_P(c_uint8), _P(c_uint8), c_int, c_int, c_int, c_int], _P(SDL_Cursor))(data, mask, w, h, hot_x, hot_y)
def SDL_CreateColorCursor(surface: SDL_Surface, hot_x: int, hot_y: int): return SDLFunc("SDL_CreateColorCursor", [_P(SDL_Surface), c_int, c_int], _P(SDL_Cursor))(surface, hot_x, hot_y)
def SDL_CreateSystemCursor(cursor: SDL_SystemCursor | int): return SDLFunc("SDL_CreateSystemCursor", [SDL_SystemCursor], _P(SDL_Cursor))(cursor)
def SDL_SetCursor(cursor: SDL_Cursor): SDLFunc("SDL_SetCursor", [_P(SDL_Cursor)])(cursor)
def SDL_GetCursor(): return SDLFunc("SDL_GetCursor", None, _P(SDL_Cursor))()
def SDL_GetDefaultCursor(): return SDLFunc("SDL_GetDefaultCursor", None, _P(SDL_Cursor))()
def SDL_ShowCursor(toggle: bool): return bool(SDLFunc("SDL_ShowCursor", [c_int], c_int)(toggle))
def SDL_CaptureMouse(enabled): return SDLFunc("SDL_CaptureMouse", [SDL_bool], c_int)(enabled)
def SDL_FreeCursor(cursor: SDL_Cursor): SDLFunc("SDL_FreeCursor", [_P(SDL_Cursor)])(cursor)

# -- Joystick -- #

def SDL_LockJoysticks(): SDLFunc("SDL_LockJoysticks", None, None)()
def SDL_UnlockJoysticks(): SDLFunc("SDL_UnlockJoysticks", None, None)()
def SDL_NumJoysticks(): return SDLFunc("SDL_NumJoysticks", None, c_int)()
def SDL_JoystickNameForIndex(index): return SDLFunc("SDL_JoystickNameForIndex", [c_int], c_char_p)(index)
def SDL_JoystickPathForIndex(index): return SDLFunc("SDL_JoystickPathForIndex", [c_int], c_char_p)(index)
def SDL_JoystickGetDevicePlayerIndex(index): return SDLFunc("SDL_JoystickGetDevicePlayerIndex", [c_int], c_int)(index)
def SDL_JoystickGetDeviceGUID(index): return SDLFunc("SDL_JoystickGetDeviceGUID", [c_int], SDL_JoystickGUID)(index)
def SDL_JoystickGetDeviceVendor(index): return SDLFunc("SDL_JoystickGetDeviceVendor", [c_int], c_uint16)(index)
def SDL_JoystickGetDeviceProduct(index): return SDLFunc("SDL_JoystickGetDeviceProduct", [c_int], c_uint16)(index)
def SDL_JoystickGetDeviceProductVersion(index): return SDLFunc("SDL_JoystickGetDeviceProductVersion", [c_int], c_uint16)(index)
def SDL_JoystickGetDeviceType(index): return SDLFunc("SDL_JoystickGetDeviceType", [c_int], SDL_JoystickType)(index)
def SDL_JoystickGetDeviceInstanceID(index): return SDLFunc("SDL_JoystickGetDeviceInstanceID", [c_int], SDL_JoystickID)(index)
def SDL_JoystickOpen(index): return SDLFunc("SDL_JoystickOpen", [c_int], _P(SDL_Joystick))(index)
def SDL_JoystickFromInstanceID(joyid): return SDLFunc("SDL_JoystickFromInstanceID", [SDL_JoystickID], _P(SDL_Joystick))(joyid)
def SDL_JoystickFromPlayerIndex(player_index): return SDLFunc("SDL_JoystickFromPlayerIndex", [c_int], _P(SDL_Joystick))(player_index)
def SDL_JoystickAttachVirtual(jtype, naxes, nbuttons, nhats): return SDLFunc("SDL_JoystickAttachVirtual", [SDL_JoystickType, c_int, c_int, c_int], returns=c_int)(jtype, naxes, nbuttons, nhats)
def SDL_JoystickAttachVirtualEx(desc): return SDLFunc("SDL_JoystickAttachVirtualEx", [_P(SDL_VirtualJoystickDesc)], c_int)(desc)
def SDL_JoystickDetachVirtual(device_index): return SDLFunc("SDL_JoystickDetachVirtual", [c_int], c_int)(device_index)
def SDL_JoystickIsVirtual(device_index): return SDLFunc("SDL_JoystickIsVirtual", [c_int], SDL_bool)(device_index)
def SDL_JoystickSetVirtualAxis(joystick, axis, value): return SDLFunc("SDL_JoystickSetVirtualAxis", [_P(SDL_Joystick), c_int, c_int16], returns=c_int)(joystick, axis, value)
def SDL_JoystickSetVirtualButton(joystick, button, value): return SDLFunc("SDL_JoystickSetVirtualButton", [_P(SDL_Joystick), c_int, c_uint8], returns=c_int)(joystick, button, value)
def SDL_JoystickSetVirtualHat(joystick, hat, value): return SDLFunc("SDL_JoystickSetVirtualHat", [_P(SDL_Joystick), c_int, c_uint8], c_int)(joystick, hat, value)
def SDL_JoystickName(joystick): return SDLFunc("SDL_JoystickName", [_P(SDL_Joystick)], c_char_p)(joystick)
def SDL_JoystickPath(joystick): return SDLFunc("SDL_JoystickPath", [_P(SDL_Joystick)], c_char_p)(joystick)
def SDL_JoystickGetPlayerIndex(joystick): return SDLFunc("SDL_JoystickGetPlayerIndex", [_P(SDL_Joystick)], c_int)(joystick)
def SDL_JoystickSetPlayerIndex(joystick, player_index): SDLFunc("SDL_JoystickSetPlayerIndex", [_P(SDL_Joystick), c_int])(joystick, player_index)
def SDL_JoystickGetGUID(joystick): return SDLFunc("SDL_JoystickGetGUID", [_P(SDL_Joystick)], SDL_JoystickGUID)(joystick)
def SDL_JoystickGetVendor(joystick): return SDLFunc("SDL_JoystickGetVendor", [_P(SDL_Joystick)], c_uint16)(joystick)
def SDL_JoystickGetProduct(joystick): return SDLFunc("SDL_JoystickGetProduct", [_P(SDL_Joystick)], c_uint16)(joystick)
def SDL_JoystickGetProductVersion(joystick): return SDLFunc("SDL_JoystickGetProductVersion", [_P(SDL_Joystick)], c_uint16)(joystick)
def SDL_JoystickGetFirmwareVersion(joystick): return SDLFunc("SDL_JoystickGetFirmwareVersion", [_P(SDL_Joystick)], c_uint16)(joystick)
def SDL_JoystickGetSerial(joystick): return SDLFunc("SDL_JoystickGetSerial", [_P(SDL_Joystick)], c_char_p)(joystick)
def SDL_JoystickGetType(joystick): return SDLFunc("SDL_JoystickGetType", [_P(SDL_Joystick)], SDL_JoystickType)(joystick)
def SDL_JoystickGetGUIDFromString(pchguid): return SDLFunc("SDL_JoystickGetGUIDFromString", [c_char_p], SDL_JoystickGUID)(pchguid)
def SDL_JoystickGetAttached(joystick): return SDLFunc("SDL_JoystickGetAttached", [_P(SDL_Joystick)], SDL_bool)(joystick)
def SDL_JoystickInstanceID(joystick): return SDLFunc("SDL_JoystickInstanceID", [_P(SDL_Joystick)], SDL_JoystickID)(joystick)
def SDL_JoystickNumAxes(joystick): return SDLFunc("SDL_JoystickNumAxes", [_P(SDL_Joystick)], c_int)(joystick)
def SDL_JoystickNumBalls(joystick): return SDLFunc("SDL_JoystickNumBalls", [_P(SDL_Joystick)], c_int)(joystick)
def SDL_JoystickNumHats(joystick): return SDLFunc("SDL_JoystickNumHats", [_P(SDL_Joystick)], c_int)(joystick)
def SDL_JoystickNumButtons(joystick): return SDLFunc("SDL_JoystickNumButtons", [_P(SDL_Joystick)], c_int)(joystick)
def SDL_JoystickUpdate(): SDLFunc("SDL_JoystickUpdate")()
def SDL_JoystickEventState(state): return SDLFunc("SDL_JoystickEventState", [c_int], c_int)(state)
def SDL_JoystickGetAxis(joystick, axis): return SDLFunc("SDL_JoystickGetAxis", [_P(SDL_Joystick), c_int], c_int16)(joystick, axis)
def SDL_JoystickGetAxisInitialState(joystick, axis, state): return SDLFunc("SDL_JoystickGetAxisInitialState", [_P(SDL_Joystick), c_int, _P(c_int16)], returns=SDL_bool)(joystick, axis, state)
def SDL_JoystickGetHat(joystick, hat): return SDLFunc("SDL_JoystickGetHat", [_P(SDL_Joystick), c_int], c_uint8)(joystick, hat)
def SDL_JoystickGetBall(joystick, ball, dx, dy): return SDLFunc("SDL_JoystickGetBall", [_P(SDL_Joystick), c_int, _P(c_int), _P(c_int)], c_int)(joystick, ball, dx, dy)
def SDL_JoystickGetButton(joystick, button): return SDLFunc("SDL_JoystickGetButton", [_P(SDL_Joystick), c_int], c_uint8)(joystick, button)
def SDL_JoystickRumble(joystick, low_frequency_rumble, high_frequency_rumble, duration_ms): return SDLFunc("SDL_JoystickRumble", [_P(SDL_Joystick), c_uint16, c_uint16, c_uint32], returns=c_int)(joystick, low_frequency_rumble, high_frequency_rumble, duration_ms)
def SDL_JoystickRumbleTriggers(joystick, left_rumble, right_rumble, duration_ms): return SDLFunc("SDL_JoystickRumbleTriggers", [_P(SDL_Joystick), c_uint16, c_uint16, c_uint32], returns=c_int)(joystick, left_rumble, right_rumble, duration_ms)
def SDL_JoystickHasLED(joystick): return SDLFunc("SDL_JoystickHasLED", [_P(SDL_Joystick)], SDL_bool)(joystick)
def SDL_JoystickHasRumble(joystick): return SDLFunc("SDL_JoystickHasRumble", [_P(SDL_Joystick)], SDL_bool)(joystick)
def SDL_JoystickHasRumbleTriggers(joystick): return SDLFunc("SDL_JoystickHasRumbleTriggers", [_P(SDL_Joystick)], SDL_bool)(joystick)
def SDL_JoystickSetLED(joystick, red, green, blue): return SDLFunc("SDL_JoystickSetLED", [_P(SDL_Joystick), c_uint8, c_uint8, c_uint8], c_int)(joystick, red, green, blue)
def SDL_JoystickSendEffect(joystick, data, size): return SDLFunc("SDL_JoystickSendEffect", [_P(SDL_Joystick), c_void_p, c_int], c_int)(joystick, data, size)
def SDL_JoystickClose(joystick): SDLFunc("SDL_JoystickClose", [_P(SDL_Joystick)])(joystick)
def SDL_JoystickCurrentPowerLevel(joystick): return SDLFunc("SDL_JoystickCurrentPowerLevel", [_P(SDL_Joystick)], returns=SDL_JoystickPowerLevel)(joystick)

# -- Controller -- #

def SDL_GameControllerAddMappingsFromRW(rw, freerw): return SDLFunc("SDL_GameControllerAddMappingsFromRW", [_P(SDL_RWops), c_int], c_int)(rw, freerw)
def SDL_GameControllerAddMappingsFromFile(fname): return SDL_GameControllerAddMappingsFromRW(SDL_RWFromFile(fname, "rb"), 1)
def SDL_GameControllerAddMapping(mapping_string): return SDLFunc("SDL_GameControllerAddMapping", [c_char_p], c_int)(mapping_string)
def SDL_GameControllerNumMappings(): return SDLFunc("SDL_GameControllerNumMappings", None, c_int)()
def SDL_GameControllerMappingForIndex(index): return SDLFunc("SDL_GameControllerMappingForIndex", [c_int], c_char_p)(index)
def SDL_GameControllerMapping(gamecontroller): return SDLFunc("SDL_GameControllerMapping", [_P(SDL_GameController)], c_char_p)(gamecontroller)
def SDL_IsGameController(joystick_index): return SDLFunc("SDL_IsGameController", [c_int], SDL_bool)(joystick_index)
def SDL_GameControllerNameForIndex(index): return SDLFunc("SDL_GameControllerNameForIndex", [c_int], c_char_p)(index)
def SDL_GameControllerPathForIndex(index): return SDLFunc("SDL_GameControllerPathForIndex", [c_int], c_char_p)(index)
def SDL_GameControllerTypeForIndex(index): return SDLFunc("SDL_GameControllerTypeForIndex", [c_int], SDL_GameControllerType)(index)
def SDL_GameControllerMappingForDeviceIndex(index): return SDLFunc("SDL_GameControllerMappingForDeviceIndex", [c_int], c_char_p)(index)
def SDL_GameControllerOpen(joystick_index): return SDLFunc("SDL_GameControllerOpen", [c_int], _P(SDL_GameController))(joystick_index)
def SDL_GameControllerFromInstanceID(joyid): return SDLFunc("SDL_GameControllerFromInstanceID", [SDL_JoystickID], returns=_P(SDL_GameController))(joyid)
def SDL_GameControllerFromPlayerIndex(player_index): return SDLFunc("SDL_GameControllerFromPlayerIndex", [c_int], _P(SDL_GameController))(player_index)
def SDL_GameControllerName(gamecontroller): return SDLFunc("SDL_GameControllerName", [_P(SDL_GameController)], c_char_p)(gamecontroller)
def SDL_GameControllerPath(gamecontroller): return SDLFunc("SDL_GameControllerPath", [_P(SDL_GameController)], c_char_p)(gamecontroller)
def SDL_GameControllerGetType(gamecontroller): return SDLFunc("SDL_GameControllerGetType", [_P(SDL_GameController)], returns=SDL_GameControllerType)(gamecontroller)
def SDL_GameControllerGetPlayerIndex(gamecontroller): return SDLFunc("SDL_GameControllerGetPlayerIndex", [_P(SDL_GameController)], c_int)(gamecontroller)
def SDL_GameControllerSetPlayerIndex(gamecontroller, player_index): SDLFunc("SDL_GameControllerSetPlayerIndex", [_P(SDL_GameController), c_int])(gamecontroller, player_index)
def SDL_GameControllerGetVendor(gamecontroller): return SDLFunc("SDL_GameControllerGetVendor", [_P(SDL_GameController)], c_uint16)(gamecontroller)
def SDL_GameControllerGetProduct(gamecontroller): return SDLFunc("SDL_GameControllerGetProduct", [_P(SDL_GameController)], c_uint16)(gamecontroller)
def SDL_GameControllerGetProductVersion(gamecontroller): return SDLFunc("SDL_GameControllerGetProductVersion", [_P(SDL_GameController)], returns=c_uint16)(gamecontroller)
def SDL_GameControllerGetFirmwareVersion(gamecontroller): return SDLFunc("SDL_GameControllerGetFirmwareVersion", [_P(SDL_GameController)], returns=c_uint16)(gamecontroller)
def SDL_GameControllerGetSerial(gamecontroller): return SDLFunc("SDL_GameControllerGetSerial", [_P(SDL_GameController)], c_char_p)(gamecontroller)
def SDL_GameControllerGetAttached(gamecontroller): return SDLFunc("SDL_GameControllerGetAttached", [_P(SDL_GameController)], SDL_bool)(gamecontroller)
def SDL_GameControllerGetJoystick(gamecontroller): return SDLFunc("SDL_GameControllerGetJoystick", [_P(SDL_GameController)], _P(SDL_Joystick))(gamecontroller)
def SDL_GameControllerEventState(state): return SDLFunc("SDL_GameControllerEventState", [c_int], c_int)(state)
def SDL_GameControllerGetAxisFromString(string): return SDLFunc("SDL_GameControllerGetAxisFromString", [c_char_p], SDL_GameControllerAxis)(string)
def SDL_GameControllerGetStringForAxis(axis): return SDLFunc("SDL_GameControllerGetStringForAxis", [SDL_GameControllerAxis], c_char_p)(axis)
def SDL_GameControllerGetBindForAxis(gamecontroller, axis): return SDLFunc("SDL_GameControllerGetBindForAxis", [_P(SDL_GameController), SDL_GameControllerAxis], returns=SDL_GameControllerButtonBind)(gamecontroller, axis)
def SDL_GameControllerHasAxis(gamecontroller, axis): return SDLFunc("SDL_GameControllerHasAxis", [_P(SDL_GameController), SDL_GameControllerAxis], returns=SDL_bool)(gamecontroller, axis)
def SDL_GameControllerGetAxis(gamecontroller, axis): return SDLFunc("SDL_GameControllerGetAxis", [_P(SDL_GameController), SDL_GameControllerAxis], c_int16)(gamecontroller, axis)
def SDL_GameControllerGetButtonFromString(string): return SDLFunc("SDL_GameControllerGetButtonFromString", [c_char_p], SDL_GameControllerButton)(string)
def SDL_GameControllerGetStringForButton(button): return SDLFunc("SDL_GameControllerGetStringForButton", [SDL_GameControllerButton], c_char_p)(button)
def SDL_GameControllerGetBindForButton(gamecontroller, button): return SDLFunc("SDL_GameControllerGetBindForButton", [_P(SDL_GameController), SDL_GameControllerButton], returns=SDL_GameControllerButtonBind)(gamecontroller, button)
def SDL_GameControllerHasButton(gamecontroller, button): return SDLFunc("SDL_GameControllerHasButton", [_P(SDL_GameController), SDL_GameControllerButton], returns=SDL_bool)(gamecontroller, button)
def SDL_GameControllerGetButton(gamecontroller, button): return SDLFunc("SDL_GameControllerGetButton", [_P(SDL_GameController), SDL_GameControllerButton], returns=c_uint8)(gamecontroller, button)
def SDL_GameControllerGetNumTouchpads(gamecontroller): return SDLFunc("SDL_GameControllerGetNumTouchpads", [_P(SDL_GameController)], c_int)(gamecontroller)
def SDL_GameControllerGetNumTouchpadFingers(gamecontroller, touchpad): return SDLFunc("SDL_GameControllerGetNumTouchpadFingers", [_P(SDL_GameController), c_int], returns=c_int)(gamecontroller, touchpad)
def SDL_GameControllerGetTouchpadFinger(gamecontroller, touchpad, finger, state, x, y, pressure): return SDLFunc("SDL_GameControllerGetTouchpadFinger", [_P(SDL_GameController), c_int, c_int, _P(c_uint8), _P(c_float), _P(c_float), _P(c_float)], returns=c_int)(gamecontroller, touchpad, finger, state, x, y, pressure)
def SDL_GameControllerRumble(gamecontroller, low_frequency_rumble, high_frequency_rumble, duration_ms): return SDLFunc("SDL_GameControllerRumble", [_P(SDL_GameController), c_uint16, c_uint16, c_uint32], returns=c_int)(gamecontroller, low_frequency_rumble, high_frequency_rumble, duration_ms)
def SDL_GameControllerRumbleTriggers(gamecontroller, left_rumble, right_rumble, duration_ms): return SDLFunc("SDL_GameControllerRumbleTriggers", [_P(SDL_GameController), c_uint16, c_uint16, c_uint32], returns=c_int)(gamecontroller, left_rumble, right_rumble, duration_ms)
def SDL_GameControllerHasLED(gamecontroller): return SDLFunc("SDL_GameControllerHasLED", [_P(SDL_GameController)], SDL_bool)(gamecontroller)
def SDL_GameControllerHasRumble(gamecontroller): return SDLFunc("SDL_GameControllerHasRumble", [_P(SDL_GameController)], SDL_bool)(gamecontroller)
def SDL_GameControllerHasRumbleTriggers(gamecontroller): return SDLFunc("SDL_GameControllerHasRumbleTriggers", [_P(SDL_GameController)], returns=SDL_bool)(gamecontroller)
def SDL_GameControllerSetLED(gamecontroller, red, green, blue): return SDLFunc("SDL_GameControllerSetLED", [_P(SDL_GameController), c_uint8, c_uint8, c_uint8], returns=c_int)(gamecontroller, red, green, blue)
def SDL_GameControllerSendEffect(gamecontroller, data, size): return SDLFunc("SDL_GameControllerSendEffect", [_P(SDL_GameController), c_void_p, c_int], returns=c_int)(gamecontroller, data, size)
def SDL_GameControllerClose(gamecontroller): SDLFunc("SDL_GameControllerClose", [_P(SDL_GameController)])(gamecontroller)
def SDL_GameControllerGetSteamHandle(gamecontroller): return SDLFunc("SDL_GameControllerGetSteamHandle", [_P(SDL_GameController)], c_uint64)(gamecontroller)

# -- Events -- #

def SDL_PumpEvents(): SDLFunc("SDL_PumpEvents")()
def SDL_PeepEvents(*args): return SDLFunc("SDL_PeepEvents", [_P(SDL_Event), c_int, SDL_eventaction, c_uint32, c_uint32], c_int)(*args)
