-- | Runs a Caramia context with OpenGL context created by the SDL2 library.
--
-- This initializes the SDL2 library (SDL_Init()) and then quits it after
-- action is done (SDL_Quit()).
--
-- If something goes wrong, `SDLError` exception is thrown.
runSDL2Context :: ContextCreation
               -> IO a
               -> IO a
runSDL2Context creation action = mask $ \restore -> runInBoundThread $ do
    is_it_zero <- SDL.init initFlagEverything
    unless (is_it_zero == 0) $ throwSDLError

    finally ?? SDL.quit $ do
        -- Set the OpenGL attributes; we need them.
        _ <- glSetAttribute glAttrContextMajorVersion 3
        _ <- glSetAttribute glAttrContextMinorVersion 2
        _ <- glSetAttribute glAttrContextProfileMask glProfileCore
        maybe (return ())
              (\_ -> void $
                  glSetAttribute glAttrContextFlags glContextFlagDebug)
                =<< lookupEnv "CARAMIA_OPENGL_DEBUG"

        window <- withCString (T.unpack (title creation)) $ \cstr ->
            createWindow cstr
                         windowPosUndefined
                         windowPosUndefined
                         (fromIntegral w)
                         (fromIntegral h)
                         (windowFlagOpenGL .|.
                          windowFlagShown .|.
                          moreFlags)

        when (nullPtr == window) throwSDLError

        finally ?? SDL.destroyWindow window $ do
            context <- glCreateContext window
            when (nullPtr == context) throwSDLError

            finally ?? glDeleteContext context $ giveContext $ do
                storeContextLocalData (SDLContextLocal window)
                restore action

  where
    moreFlags = (case sizing creation of
        Fullscreen _ _ -> windowFlagFullscreen
        FullscreenNativeRes -> windowFlagFullscreenDesktop
        Windowed _ _ -> 0) .|.
                (if allowResizing creation
                  then windowFlagResizable
                  else 0)
    (w, h) = case sizing creation of
        Fullscreen w h -> (w, h)
        Windowed w h   -> (w, h)
        FullscreenNativeRes -> (1, 1)

-- | Swaps buffers in the current context.
--
-- This also runs pending finalizers `Caramia.Context.runPendingFinalizers`.
runSDL2Context :: ContextCreation
               -> IO a
               -> IO a
runSDL2Context creation action = mask $ \restore -> runInBoundThread $ do
    is_it_zero <- SDL.init initFlagEverything
    unless (is_it_zero == 0) $ throwSDLError

    finally ?? SDL.quit $ do
        -- Set the OpenGL attributes; we need them.
        _ <- glSetAttribute glAttrContextMajorVersion 3
        _ <- glSetAttribute glAttrContextMinorVersion 2
        _ <- glSetAttribute glAttrContextProfileMask glProfileCore
        maybe (return ())
              (\_ -> void $
                  glSetAttribute glAttrContextFlags glContextFlagDebug)
                =<< lookupEnv "CARAMIA_OPENGL_DEBUG"

        window <- withCString (T.unpack (title creation)) $ \cstr ->
            createWindow cstr
                         windowPosUndefined
                         windowPosUndefined
                         (fromIntegral w)
                         (fromIntegral h)
                         (windowFlagOpenGL .|.
                          windowFlagShown .|.
                          moreFlags)

        when (nullPtr == window) throwSDLError

        finally ?? SDL.destroyWindow window $ do
            context <- glCreateContext window
            when (nullPtr == context) throwSDLError

            finally ?? glDeleteContext context $ giveContext $ do
                storeContextLocalData (SDLContextLocal window)
                restore action

  where
    moreFlags = (case sizing creation of
        Fullscreen _ _ -> windowFlagFullscreen
        FullscreenNativeRes -> windowFlagFullscreenDesktop
        Windowed _ _ -> 0) .|.
                (if allowResizing creation
                  then windowFlagResizable
                  else 0)
    (w, h) = case sizing creation of
        Fullscreen w h -> (w, h)
        Windowed w h   -> (w, h)
        FullscreenNativeRes -> (1, 1)

-- | Swaps buffers in the current context.
--
-- This also runs pending finalizers `Caramia.Context.runPendingFinalizers`.
runSDL2Context creation action = mask $ \restore -> runInBoundThread $ do
    is_it_zero <- SDL.init initFlagEverything
    unless (is_it_zero == 0) $ throwSDLError

    finally ?? SDL.quit $ do
        -- Set the OpenGL attributes; we need them.
        _ <- glSetAttribute glAttrContextMajorVersion 3
        _ <- glSetAttribute glAttrContextMinorVersion 2
        _ <- glSetAttribute glAttrContextProfileMask glProfileCore
        maybe (return ())
              (\_ -> void $
                  glSetAttribute glAttrContextFlags glContextFlagDebug)
                =<< lookupEnv "CARAMIA_OPENGL_DEBUG"

        window <- withCString (T.unpack (title creation)) $ \cstr ->
            createWindow cstr
                         windowPosUndefined
                         windowPosUndefined
                         (fromIntegral w)
                         (fromIntegral h)
                         (windowFlagOpenGL .|.
                          windowFlagShown .|.
                          moreFlags)

        when (nullPtr == window) throwSDLError

        finally ?? SDL.destroyWindow window $ do
            context <- glCreateContext window
            when (nullPtr == context) throwSDLError

            finally ?? glDeleteContext context $ giveContext $ do
                storeContextLocalData (SDLContextLocal window)
                restore action

  where
    moreFlags = (case sizing creation of
        Fullscreen _ _ -> windowFlagFullscreen
        FullscreenNativeRes -> windowFlagFullscreenDesktop
        Windowed _ _ -> 0) .|.
                (if allowResizing creation
                  then windowFlagResizable
                  else 0)
    (w, h) = case sizing creation of
        Fullscreen w h -> (w, h)
        Windowed w h   -> (w, h)
        FullscreenNativeRes -> (1, 1)

-- | Swaps buffers in the current context.
--
-- This also runs pending finalizers `Caramia.Context.runPendingFinalizers`.