{- |
Copyright  : Will Thompson, Iñaki García Etxebarria and Jonas Platte
License    : LGPL-2.1
Maintainer : Iñaki García Etxebarria (inaki@blueleaf.cc)

An opaque structure representing an opened directory.
-}

#define ENABLE_OVERLOADING (MIN_VERSION_haskell_gi_overloading(1,0,0) \
       && !defined(__HADDOCK_VERSION__))

module GI.GLib.Structs.Dir
    (

-- * Exported types
    Dir(..)                                 ,
    noDir                                   ,


 -- * Methods
-- ** close #method:close#

#if ENABLE_OVERLOADING
    DirCloseMethodInfo                      ,
#endif
    dirClose                                ,


-- ** makeTmp #method:makeTmp#

    dirMakeTmp                              ,


-- ** readName #method:readName#

#if ENABLE_OVERLOADING
    DirReadNameMethodInfo                   ,
#endif
    dirReadName                             ,


-- ** rewind #method:rewind#

#if ENABLE_OVERLOADING
    DirRewindMethodInfo                     ,
#endif
    dirRewind                               ,




    ) where

import Data.GI.Base.ShortPrelude
import qualified Data.GI.Base.ShortPrelude as SP
import qualified Data.GI.Base.Overloading as O
import qualified Prelude as P

import qualified Data.GI.Base.Attributes as GI.Attributes
import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr
import qualified Data.GI.Base.GClosure as B.GClosure
import qualified Data.GI.Base.GError as B.GError
import qualified Data.GI.Base.GVariant as B.GVariant
import qualified Data.GI.Base.GValue as B.GValue
import qualified Data.GI.Base.GParamSpec as B.GParamSpec
import qualified Data.GI.Base.CallStack as B.CallStack
import qualified Data.GI.Base.Properties as B.Properties
import qualified Data.Text as T
import qualified Data.ByteString.Char8 as B
import qualified Data.Map as Map
import qualified Foreign.Ptr as FP
import qualified GHC.OverloadedLabels as OL


-- | Memory-managed wrapper type.
newtype Dir = Dir (ManagedPtr Dir)
-- XXX Wrapping a foreign struct/union with no known destructor or size, leak?
instance WrappedPtr Dir where
    wrappedPtrCalloc = return nullPtr
    wrappedPtrCopy = return
    wrappedPtrFree = Nothing

-- | A convenience alias for `Nothing` :: `Maybe` `Dir`.
noDir :: Maybe Dir
noDir = Nothing


#if ENABLE_OVERLOADING
instance O.HasAttributeList Dir
type instance O.AttributeList Dir = DirAttributeList
type DirAttributeList = ('[ ] :: [(Symbol, *)])
#endif

-- method Dir::close
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "dir", argType = TInterface (Name {namespace = "GLib", name = "Dir"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GDir* created by g_dir_open()", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_dir_close" g_dir_close ::
    Ptr Dir ->                              -- dir : TInterface (Name {namespace = "GLib", name = "Dir"})
    IO ()

{- |
Closes the directory and deallocates all related resources.
-}
dirClose ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Dir
    {- ^ /@dir@/: a 'GI.GLib.Structs.Dir.Dir'* created by @/g_dir_open()/@ -}
    -> m ()
dirClose dir = liftIO $ do
    dir' <- unsafeManagedPtrGetPtr dir
    g_dir_close dir'
    touchManagedPtr dir
    return ()

#if ENABLE_OVERLOADING
data DirCloseMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.MethodInfo DirCloseMethodInfo Dir signature where
    overloadedMethod _ = dirClose

#endif

-- method Dir::read_name
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "dir", argType = TInterface (Name {namespace = "GLib", name = "Dir"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GDir* created by g_dir_open()", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TBasicType TFileName)
-- throws : False
-- Skip return : False

foreign import ccall "g_dir_read_name" g_dir_read_name ::
    Ptr Dir ->                              -- dir : TInterface (Name {namespace = "GLib", name = "Dir"})
    IO CString

{- |
Retrieves the name of another entry in the directory, or 'Nothing'.
The order of entries returned from this function is not defined,
and may vary by file system or other operating-system dependent
factors.

'Nothing' may also be returned in case of errors. On Unix, you can
check @errno@ to find out if 'Nothing' was returned because of an error.

On Unix, the \'.\' and \'..\' entries are omitted, and the returned
name is in the on-disk encoding.

On Windows, as is true of all GLib functions which operate on
filenames, the returned name is in UTF-8.
-}
dirReadName ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Dir
    {- ^ /@dir@/: a 'GI.GLib.Structs.Dir.Dir'* created by @/g_dir_open()/@ -}
    -> m [Char]
    {- ^ __Returns:__ The entry\'s name or 'Nothing' if there are no
  more entries. The return value is owned by GLib and
  must not be modified or freed. -}
dirReadName dir = liftIO $ do
    dir' <- unsafeManagedPtrGetPtr dir
    result <- g_dir_read_name dir'
    checkUnexpectedReturnNULL "dirReadName" result
    result' <- cstringToString result
    touchManagedPtr dir
    return result'

#if ENABLE_OVERLOADING
data DirReadNameMethodInfo
instance (signature ~ (m [Char]), MonadIO m) => O.MethodInfo DirReadNameMethodInfo Dir signature where
    overloadedMethod _ = dirReadName

#endif

-- method Dir::rewind
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "dir", argType = TInterface (Name {namespace = "GLib", name = "Dir"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GDir* created by g_dir_open()", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_dir_rewind" g_dir_rewind ::
    Ptr Dir ->                              -- dir : TInterface (Name {namespace = "GLib", name = "Dir"})
    IO ()

{- |
Resets the given directory. The next call to 'GI.GLib.Structs.Dir.dirReadName'
will return the first entry again.
-}
dirRewind ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Dir
    {- ^ /@dir@/: a 'GI.GLib.Structs.Dir.Dir'* created by @/g_dir_open()/@ -}
    -> m ()
dirRewind dir = liftIO $ do
    dir' <- unsafeManagedPtrGetPtr dir
    g_dir_rewind dir'
    touchManagedPtr dir
    return ()

#if ENABLE_OVERLOADING
data DirRewindMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.MethodInfo DirRewindMethodInfo Dir signature where
    overloadedMethod _ = dirRewind

#endif

-- method Dir::make_tmp
-- method type : MemberFunction
-- Args : [Arg {argCName = "tmpl", argType = TBasicType TFileName, direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "Template for directory name,\n    as in g_mkdtemp(), basename only, or %NULL for a default template", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TBasicType TFileName)
-- throws : True
-- Skip return : False

foreign import ccall "g_dir_make_tmp" g_dir_make_tmp ::
    CString ->                              -- tmpl : TBasicType TFileName
    Ptr (Ptr GError) ->                     -- error
    IO CString

{- |
Creates a subdirectory in the preferred directory for temporary
files (as returned by 'GI.GLib.Functions.getTmpDir').

/@tmpl@/ should be a string in the GLib file name encoding containing
a sequence of six \'X\' characters, as the parameter to @/g_mkstemp()/@.
However, unlike these functions, the template should only be a
basename, no directory components are allowed. If template is
'Nothing', a default template is used.

Note that in contrast to @/g_mkdtemp()/@ (and @/mkdtemp()/@) /@tmpl@/ is not
modified, and might thus be a read-only literal string.

/Since: 2.30/
-}
dirMakeTmp ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Maybe ([Char])
    {- ^ /@tmpl@/: Template for directory name,
    as in @/g_mkdtemp()/@, basename only, or 'Nothing' for a default template -}
    -> m [Char]
    {- ^ __Returns:__ The actual name used. This string
    should be freed with 'GI.GLib.Functions.free' when not needed any longer and is
    is in the GLib file name encoding. In case of errors, 'Nothing' is
    returned and /@error@/ will be set. /(Can throw 'Data.GI.Base.GError.GError')/ -}
dirMakeTmp tmpl = liftIO $ do
    maybeTmpl <- case tmpl of
        Nothing -> return nullPtr
        Just jTmpl -> do
            jTmpl' <- stringToCString jTmpl
            return jTmpl'
    onException (do
        result <- propagateGError $ g_dir_make_tmp maybeTmpl
        checkUnexpectedReturnNULL "dirMakeTmp" result
        result' <- cstringToString result
        freeMem result
        freeMem maybeTmpl
        return result'
     ) (do
        freeMem maybeTmpl
     )

#if ENABLE_OVERLOADING
#endif

#if ENABLE_OVERLOADING
type family ResolveDirMethod (t :: Symbol) (o :: *) :: * where
    ResolveDirMethod "close" o = DirCloseMethodInfo
    ResolveDirMethod "readName" o = DirReadNameMethodInfo
    ResolveDirMethod "rewind" o = DirRewindMethodInfo
    ResolveDirMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveDirMethod t Dir, O.MethodInfo info Dir p) => OL.IsLabel t (Dir -> p) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
#else
    fromLabel _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
#endif

#endif