    module SDL.Raw.Basic (
      -- * Initialization and Shutdown
      init,
      initSubSystem,
      quit,
      quitSubSystem,
      setMainReady,
      wasInit,

      -- * Memory Management
      free,

      -- * Configuration Variables
      addHintCallback,
      clearHints,
      delHintCallback,
      getHint,
      setHint,
      setHintWithPriority,

      -- * Log Handling
      log,
      logCritical,
      logDebug,
      logError,
      logGetOutputFunction,
      logGetPriority,
      logInfo,
      logMessage,
      logResetPriorities,
      logSetAllPriority,
      logSetOutputFunction,
      logSetPriority,
      logVerbose,
      logWarn,

      -- * Assertions
      -- | Use Haskell's own assertion primitives rather than SDL's.

      -- * Querying SDL Version
      getRevision,
      getRevisionNumber,
      getVersion
    ) where

    import Control.Monad.IO.Class
    import Foreign.C.String
    import Foreign.C.Types
    import Foreign.Ptr
    import SDL.Raw.Enum
    import SDL.Raw.Types
    import Prelude hiding (init, log)

    foreign import ccall "SDL.h SDL_Init" initFFI :: InitFlag -> IO CInt
    foreign import ccall "SDL.h SDL_InitSubSystem" initSubSystemFFI :: InitFlag -> IO CInt
    foreign import ccall "SDL.h SDL_Quit" quitFFI :: IO ()
    foreign import ccall "SDL.h SDL_QuitSubSystem" quitSubSystemFFI :: InitFlag -> IO ()
    foreign import ccall "SDL.h SDL_SetMainReady" setMainReadyFFI :: IO ()
    foreign import ccall "SDL.h SDL_WasInit" wasInitFFI :: InitFlag -> IO InitFlag

    foreign import ccall "SDL.h SDL_free" freeFFI :: Ptr () -> IO ()

    foreign import ccall "SDL.h SDL_AddHintCallback" addHintCallbackFFI :: CString -> HintCallback -> Ptr () -> IO ()
    foreign import ccall "SDL.h SDL_ClearHints" clearHintsFFI :: IO ()
    foreign import ccall "SDL.h SDL_DelHintCallback" delHintCallbackFFI :: CString -> HintCallback -> Ptr () -> IO ()
    foreign import ccall "SDL.h SDL_GetHint" getHintFFI :: CString -> IO CString
    foreign import ccall "SDL.h SDL_SetHint" setHintFFI :: CString -> CString -> IO Bool
    foreign import ccall "SDL.h SDL_SetHintWithPriority" setHintWithPriorityFFI :: CString -> CString -> HintPriority -> IO Bool

    foreign import ccall "SDL.h SDL_LogGetOutputFunction" logGetOutputFunctionFFI :: Ptr LogOutputFunction -> Ptr (Ptr ()) -> IO ()
    foreign import ccall "SDL.h SDL_LogGetPriority" logGetPriorityFFI :: CInt -> IO LogPriority
    foreign import ccall "sdlhelper.c SDLHelper_LogMessage" logMessageFFI :: CInt -> LogPriority -> CString -> IO ()
    foreign import ccall "SDL.h SDL_LogResetPriorities" logResetPrioritiesFFI :: IO ()
    foreign import ccall "SDL.h SDL_LogSetAllPriority" logSetAllPriorityFFI :: LogPriority -> IO ()
    foreign import ccall "SDL.h SDL_LogSetOutputFunction" logSetOutputFunctionFFI :: LogOutputFunction -> Ptr () -> IO ()
    foreign import ccall "SDL.h SDL_LogSetPriority" logSetPriorityFFI :: CInt -> LogPriority -> IO ()

    foreign import ccall "SDL.h SDL_GetRevision" getRevisionFFI :: IO CString
    foreign import ccall "SDL.h SDL_GetRevisionNumber" getRevisionNumberFFI :: IO CInt
    foreign import ccall "SDL.h SDL_GetVersion" getVersionFFI :: Ptr Version -> IO ()

    init :: MonadIO m => InitFlag -> m CInt
    init :: InitFlag -> m CInt
    init v1 :: InitFlag
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ InitFlag -> IO CInt
    initFFI InitFlag
    v1
    {-# INLINE init #-}

    initSubSystem :: MonadIO m => InitFlag -> m CInt
    initSubSystem :: InitFlag -> m CInt
    initSubSystem v1 :: InitFlag
    v1 = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CInt -> m CInt) -> IO CInt -> m CInt
    forall a b. (a -> b) -> a -> b
    $ InitFlag -> IO CInt
    initSubSystemFFI InitFlag
    v1
    {-# INLINE initSubSystem #-}

    quit :: MonadIO m => m ()
    quit :: m ()
    quit = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO ()
    quitFFI
    {-# INLINE quit #-}

    quitSubSystem :: MonadIO m => InitFlag -> m ()
    quitSubSystem :: InitFlag -> m ()
    quitSubSystem v1 :: InitFlag
    v1 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ InitFlag -> IO ()
    quitSubSystemFFI InitFlag
    v1
    {-# INLINE quitSubSystem #-}

    setMainReady :: MonadIO m => m ()
    setMainReady :: m ()
    setMainReady = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO ()
    setMainReadyFFI
    {-# INLINE setMainReady #-}

    wasInit :: MonadIO m => InitFlag -> m InitFlag
    wasInit :: InitFlag -> m InitFlag
    wasInit v1 :: InitFlag
    v1 = IO InitFlag -> m InitFlag
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO InitFlag -> m InitFlag) -> IO InitFlag -> m InitFlag
    forall a b. (a -> b) -> a -> b
    $ InitFlag -> IO InitFlag
    wasInitFFI InitFlag
    v1
    {-# INLINE wasInit #-}

    free :: MonadIO m => Ptr () -> m ()
    free :: Ptr () -> m ()
    free v1 :: Ptr ()
    v1 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr () -> IO ()
    freeFFI Ptr ()
    v1
    {-# INLINE free #-}

    addHintCallback :: MonadIO m => CString -> HintCallback -> Ptr () -> m ()
    addHintCallback :: CString -> HintCallback -> Ptr () -> m ()
    addHintCallback v1 :: CString
    v1 v2 :: HintCallback
    v2 v3 :: Ptr ()
    v3 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ CString -> HintCallback -> Ptr () -> IO ()
    addHintCallbackFFI CString
    v1 HintCallback
    v2 Ptr ()
    v3
    {-# INLINE addHintCallback #-}

    clearHints :: MonadIO m => m ()
    clearHints :: m ()
    clearHints = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO ()
    clearHintsFFI
    {-# INLINE clearHints #-}

    delHintCallback :: MonadIO m => CString -> HintCallback -> Ptr () -> m ()
    delHintCallback :: CString -> HintCallback -> Ptr () -> m ()
    delHintCallback v1 :: CString
    v1 v2 :: HintCallback
    v2 v3 :: Ptr ()
    v3 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ CString -> HintCallback -> Ptr () -> IO ()
    delHintCallbackFFI CString
    v1 HintCallback
    v2 Ptr ()
    v3
    {-# INLINE delHintCallback #-}

    getHint :: MonadIO m => CString -> m CString
    getHint :: CString -> m CString
    getHint v1 :: CString
    v1 = IO CString -> m CString
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO CString -> m CString) -> IO CString -> m CString
    forall a b. (a -> b) -> a -> b
    $ CString -> IO CString
    getHintFFI CString
    v1
    {-# INLINE getHint #-}

    setHint :: MonadIO m => CString -> CString -> m Bool
    setHint :: CString -> CString -> m Bool
    setHint v1 :: CString
    v1 v2 :: CString
    v2 = IO Bool -> m Bool
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Bool -> m Bool) -> IO Bool -> m Bool
    forall a b. (a -> b) -> a -> b
    $ CString -> CString -> IO Bool
    setHintFFI CString
    v1 CString
    v2
    {-# INLINE setHint #-}

    setHintWithPriority :: MonadIO m => CString -> CString -> HintPriority -> m Bool
    setHintWithPriority :: CString -> CString -> InitFlag -> m Bool
    setHintWithPriority v1 :: CString
    v1 v2 :: CString
    v2 v3 :: InitFlag
    v3 = IO Bool -> m Bool
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Bool -> m Bool) -> IO Bool -> m Bool
    forall a b. (a -> b) -> a -> b
    $ CString -> CString -> InitFlag -> IO Bool
    setHintWithPriorityFFI CString
    v1 CString
    v2 InitFlag
    v3
    {-# INLINE setHintWithPriority #-}

    log :: CString -> IO ()
    log :: CString -> IO ()
    log = CInt -> InitFlag -> CString -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    CInt -> InitFlag -> CString -> m ()
    logMessage CInt
    forall a. (Eq a, Num a) => a
    SDL_LOG_CATEGORY_APPLICATION InitFlag
    SDL_LOG_PRIORITY_INFO
    {-# INLINE log #-}

    logCritical :: CInt -> CString -> IO ()
    logCritical :: CInt -> CString -> IO ()
    logCritical category :: CInt
    category = CInt -> InitFlag -> CString -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    CInt -> InitFlag -> CString -> m ()
    logMessage CInt
    category InitFlag
    SDL_LOG_PRIORITY_CRITICAL
    {-# INLINE logCritical #-}

    logDebug :: CInt -> CString -> IO ()
    logDebug :: CInt -> CString -> IO ()
    logDebug category :: CInt
    category = CInt -> InitFlag -> CString -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    CInt -> InitFlag -> CString -> m ()
    logMessage CInt
    category InitFlag
    SDL_LOG_PRIORITY_DEBUG
    {-# INLINE logDebug #-}

    logError :: CInt -> CString -> IO ()
    logError :: CInt -> CString -> IO ()
    logError category :: CInt
    category = CInt -> InitFlag -> CString -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    CInt -> InitFlag -> CString -> m ()
    logMessage CInt
    category InitFlag
    SDL_LOG_PRIORITY_ERROR
    {-# INLINE logError #-}

    logGetOutputFunction :: MonadIO m => Ptr LogOutputFunction -> Ptr (Ptr ()) -> m ()
    logGetOutputFunction :: Ptr LogOutputFunction -> Ptr (Ptr ()) -> m ()
    logGetOutputFunction v1 :: Ptr LogOutputFunction
    v1 v2 :: Ptr (Ptr ())
    v2 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr LogOutputFunction -> Ptr (Ptr ()) -> IO ()
    logGetOutputFunctionFFI Ptr LogOutputFunction
    v1 Ptr (Ptr ())
    v2
    {-# INLINE logGetOutputFunction #-}

    logGetPriority :: MonadIO m => CInt -> m LogPriority
    logGetPriority :: CInt -> m InitFlag
    logGetPriority v1 :: CInt
    v1 = IO InitFlag -> m InitFlag
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO InitFlag -> m InitFlag) -> IO InitFlag -> m InitFlag
    forall a b. (a -> b) -> a -> b
    $ CInt -> IO InitFlag
    logGetPriorityFFI CInt
    v1
    {-# INLINE logGetPriority #-}

    logInfo :: CInt -> CString -> IO ()
    logInfo :: CInt -> CString -> IO ()
    logInfo category :: CInt
    category = CInt -> InitFlag -> CString -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    CInt -> InitFlag -> CString -> m ()
    logMessage CInt
    category InitFlag
    SDL_LOG_PRIORITY_INFO
    {-# INLINE logInfo #-}

    logMessage :: MonadIO m => CInt -> LogPriority -> CString -> m ()
    logMessage :: CInt -> InitFlag -> CString -> m ()
    logMessage v1 :: CInt
    v1 v2 :: InitFlag
    v2 v3 :: CString
    v3 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ CInt -> InitFlag -> CString -> IO ()
    logMessageFFI CInt
    v1 InitFlag
    v2 CString
    v3
    {-# INLINE logMessage #-}

    logResetPriorities :: MonadIO m => m ()
    logResetPriorities :: m ()
    logResetPriorities = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO ()
    logResetPrioritiesFFI
    {-# INLINE logResetPriorities #-}

    logSetAllPriority :: MonadIO m => LogPriority -> m ()
    logSetAllPriority :: InitFlag -> m ()
    logSetAllPriority v1 :: InitFlag
    v1 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ InitFlag -> IO ()
    logSetAllPriorityFFI InitFlag
    v1
    {-# INLINE logSetAllPriority #-}

    logSetOutputFunction :: MonadIO m => LogOutputFunction -> Ptr () -> m ()
    logSetOutputFunction :: LogOutputFunction -> Ptr () -> m ()
    logSetOutputFunction v1 :: LogOutputFunction
    v1 v2 :: Ptr ()
    v2 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ LogOutputFunction -> Ptr () -> IO ()
    logSetOutputFunctionFFI LogOutputFunction
    v1 Ptr ()
    v2
    {-# INLINE logSetOutputFunction #-}

    logSetPriority :: MonadIO m => CInt -> LogPriority -> m ()
    logSetPriority :: CInt -> InitFlag -> m ()
    logSetPriority v1 :: CInt
    v1 v2 :: InitFlag
    v2 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ CInt -> InitFlag -> IO ()
    logSetPriorityFFI CInt
    v1 InitFlag
    v2
    {-# INLINE logSetPriority #-}

    logVerbose :: CInt -> CString -> IO ()
    logVerbose :: CInt -> CString -> IO ()
    logVerbose category :: CInt
    category = CInt -> InitFlag -> CString -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    CInt -> InitFlag -> CString -> m ()
    logMessage CInt
    category InitFlag
    SDL_LOG_PRIORITY_VERBOSE
    {-# INLINE logVerbose #-}

    logWarn :: CInt -> CString -> IO ()
    logWarn :: CInt -> CString -> IO ()
    logWarn category :: CInt
    category = CInt -> InitFlag -> CString -> IO ()
    forall (m :: * -> *).
    MonadIO m =>
    CInt -> InitFlag -> CString -> m ()
    logMessage CInt
    category InitFlag
    SDL_LOG_PRIORITY_WARN
    {-# INLINE logWarn #-}

    getRevision :: MonadIO m => m CString
    getRevision :: m CString
    getRevision = IO CString -> m CString
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO CString
    getRevisionFFI
    {-# INLINE getRevision #-}

    getRevisionNumber :: MonadIO m => m CInt
    getRevisionNumber :: m CInt
    getRevisionNumber = IO CInt -> m CInt
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO CInt
    getRevisionNumberFFI
    {-# INLINE getRevisionNumber #-}

    getVersion :: MonadIO m => Ptr Version -> m ()
    getVersion :: Ptr Version -> m ()
    getVersion v1 :: Ptr Version
    v1 = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> IO () -> m ()
    forall a b. (a -> b) -> a -> b
    $ Ptr Version -> IO ()
    getVersionFFI Ptr Version
    v1
    {-# INLINE getVersion #-}