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

    An opaque structure representing an opened directory.
    -}

    #define ENABLE_OVERLOADING \
           (!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.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.Text as T
    import qualified Data.ByteString.Char8 as B
    import qualified Data.Map as Map
    import qualified Foreign.Ptr as FP

    -- | 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) => O.IsLabelProxy t (Dir -> p) where
        fromLabelProxy _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)

    #if MIN_VERSION_base(4,9,0)
    instance (info ~ ResolveDirMethod t Dir, O.MethodInfo info Dir p) => O.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

    #endif