{-# LANGUAGE CPP#-}
{-# LANGUAGE OverloadedStrings #-}

module SDL.Filesystem
  ( -- * Filesystem Paths
    getBasePath
  , getPrefPath
) where

import Control.Exception
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Text (Text)
import Foreign.Marshal.Alloc
import SDL.Internal.Exception
import qualified Data.ByteString as BS
import qualified Data.Text.Encoding as Text
import qualified SDL.Raw.Filesystem as Raw

#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
#endif

-- | An absolute path to the application data directory.
--
-- The path is guaranteed to end with a path separator.
--
-- Throws 'SDLException' on failure, or if the platform does not implement this
-- functionality.
getBasePath :: MonadIO m => m Text
getBasePath :: m Text
getBasePath = IO Text -> m Text
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Text -> m Text) -> IO Text -> m Text
forall a b. (a -> b) -> a -> b
$ IO Text -> IO Text
forall a. IO a -> IO a
mask_ (IO Text -> IO Text) -> IO Text -> IO Text
forall a b. (a -> b) -> a -> b
$ do
  Ptr CChar
cpath <- Text -> Text -> IO (Ptr CChar) -> IO (Ptr CChar)
forall (m :: * -> *) a.
MonadIO m =>
Text -> Text -> m (Ptr a) -> m (Ptr a)
throwIfNull "SDL.Filesystem.getBasePath" "SDL_GetBasePath"
    IO (Ptr CChar)
forall (m :: * -> *). MonadIO m => m (Ptr CChar)
Raw.getBasePath
  IO Text -> IO () -> IO Text
forall a b. IO a -> IO b -> IO a
finally (ByteString -> Text
Text.decodeUtf8 (ByteString -> Text) -> IO ByteString -> IO Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CChar -> IO ByteString
BS.packCString Ptr CChar
cpath) (Ptr CChar -> IO ()
forall a. Ptr a -> IO ()
free Ptr CChar
cpath)

-- | A path to a unique per user and per application directory for the given
-- organization and application name, intended for writing preferences and
-- other personal files.
--
-- The path is guaranteed to end with a path separator.
--
-- You should assume the path returned by this function is the only safe place
-- to write files to.
--
-- Throws 'SDLException' on failure.
getPrefPath :: MonadIO m => Text -> Text -> m Text
getPrefPath :: Text -> Text -> m Text
getPrefPath organization :: Text
organization application :: Text
application = IO Text -> m Text
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Text -> m Text) -> IO Text -> m Text
forall a b. (a -> b) -> a -> b
$ IO Text -> IO Text
forall a. IO a -> IO a
mask_ (IO Text -> IO Text) -> IO Text -> IO Text
forall a b. (a -> b) -> a -> b
$ do
  Ptr CChar
cpath <- Text -> Text -> IO (Ptr CChar) -> IO (Ptr CChar)
forall (m :: * -> *) a.
MonadIO m =>
Text -> Text -> m (Ptr a) -> m (Ptr a)
throwIfNull "SDL.Filesystem.getPrefPath" "SDL_GetPrefPath" (IO (Ptr CChar) -> IO (Ptr CChar))
-> IO (Ptr CChar) -> IO (Ptr CChar)
forall a b. (a -> b) -> a -> b
$
    ByteString -> (Ptr CChar -> IO (Ptr CChar)) -> IO (Ptr CChar)
forall a. ByteString -> (Ptr CChar -> IO a) -> IO a
BS.useAsCString (Text -> ByteString
Text.encodeUtf8 Text
organization) ((Ptr CChar -> IO (Ptr CChar)) -> IO (Ptr CChar))
-> (Ptr CChar -> IO (Ptr CChar)) -> IO (Ptr CChar)
forall a b. (a -> b) -> a -> b
$ \org :: Ptr CChar
org ->
      ByteString -> (Ptr CChar -> IO (Ptr CChar)) -> IO (Ptr CChar)
forall a. ByteString -> (Ptr CChar -> IO a) -> IO a
BS.useAsCString (Text -> ByteString
Text.encodeUtf8 Text
application) ((Ptr CChar -> IO (Ptr CChar)) -> IO (Ptr CChar))
-> (Ptr CChar -> IO (Ptr CChar)) -> IO (Ptr CChar)
forall a b. (a -> b) -> a -> b
$ \app :: Ptr CChar
app ->
        Ptr CChar -> Ptr CChar -> IO (Ptr CChar)
forall (m :: * -> *).
MonadIO m =>
Ptr CChar -> Ptr CChar -> m (Ptr CChar)
Raw.getPrefPath Ptr CChar
org Ptr CChar
app
  IO Text -> IO () -> IO Text
forall a b. IO a -> IO b -> IO a
finally (ByteString -> Text
Text.decodeUtf8 (ByteString -> Text) -> IO ByteString -> IO Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CChar -> IO ByteString
BS.packCString Ptr CChar
cpath) (Ptr CChar -> IO ()
forall a. Ptr a -> IO ()
free Ptr CChar
cpath)