module Graphics.UI.SDL.RWOps.PhysFS (fromPhysFile, tryFromPhysFile, withPhys) where
import Control.Arrow
import Control.Exception
import Foreign (Ptr, maybePeek)

import Graphics.UI.SDL.General (unwrapMaybe)
import Graphics.UI.SDL.RWOps
import Graphics.UI.SDL.Types (RWops, RWopsStruct)

import System.IO.PhysFS
import System.IO.PhysFS.Internal

-- |Open a PhysicsFS file, perform an action, and close the file (regardless of what happens).
withPhys :: FilePath -- ^The file to open
         -> PhysIOMode -- ^The mode to open with
         -> (RWops -> IO a) -- ^The action to perform on the resulting RWops
         -> IO a
withPhys fp mode action = bracket (fromPhysFile fp mode) free action

-- |Attempt to create a 'Graphics.UI.SDL.Types.RWops' structure from a PhysicsFS file.
tryFromPhysFile :: FilePath -- ^The file to open
                -> PhysIOMode -- ^The mode to open with
                -> IO (Maybe RWops)
tryFromPhysFile fp mode = rawOpen fp mode >>= (fst >>> createRWOps) >>= maybePeek mkFinalizedRW
foreign import ccall "physfsrwops_create_rwops" createRWOps :: Ptr PhysFS_FileStruct -> IO (Ptr RWopsStruct)

-- |Create a 'Graphics.UI.SDL.Types.RWops' structure from a PhysicsFS file. This will raise an exception if anything goes wrong.
fromPhysFile :: FilePath -- ^The file to open
             -> PhysIOMode -- ^The mode to open with
             -> IO RWops
fromPhysFile fp mode = unwrapMaybe "PHYSFS_SDL_RWFromFile" $ tryFromPhysFile fp mode
-- The name given here (PHYSFS_...) is not actually a function, but it should get the point across
