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

    A GHashTableIter structure represents an iterator that can be used
    to iterate over the elements of a 'GI.GLib.Structs.HashTable.HashTable'. GHashTableIter
    structures are typically allocated on the stack and then initialized
    with 'GI.GLib.Structs.HashTableIter.hashTableIterInit'.
    -}

    #define ENABLE_OVERLOADING \
           (!defined(__HADDOCK_VERSION__))

    module GI.GLib.Structs.HashTableIter
        (

    -- * Exported types
        HashTableIter(..)                       ,
        newZeroHashTableIter                    ,
        noHashTableIter                         ,

     -- * Methods
    -- ** init #method:init#

    #if ENABLE_OVERLOADING
        HashTableIterInitMethodInfo             ,
    #endif
        hashTableIterInit                       ,

    -- ** next #method:next#

    #if ENABLE_OVERLOADING
        HashTableIterNextMethodInfo             ,
    #endif
        hashTableIterNext                       ,

    -- ** remove #method:remove#

    #if ENABLE_OVERLOADING
        HashTableIterRemoveMethodInfo           ,
    #endif
        hashTableIterRemove                     ,

    -- ** replace #method:replace#

    #if ENABLE_OVERLOADING
        HashTableIterReplaceMethodInfo          ,
    #endif
        hashTableIterReplace                    ,

    -- ** steal #method:steal#

    #if ENABLE_OVERLOADING
        HashTableIterStealMethodInfo            ,
    #endif
        hashTableIterSteal                      ,

        ) 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 HashTableIter = HashTableIter (ManagedPtr HashTableIter)
    instance WrappedPtr HashTableIter where
        wrappedPtrCalloc = callocBytes 40
        wrappedPtrCopy = \p -> withManagedPtr p (copyBytes 40 >=> wrapPtr HashTableIter)
        wrappedPtrFree = Just ptr_to_g_free

    -- | Construct a `HashTableIter` struct initialized to zero.
    newZeroHashTableIter :: MonadIO m => m HashTableIter
    newZeroHashTableIter = liftIO $ wrappedPtrCalloc >>= wrapPtr HashTableIter

    instance tag ~ 'AttrSet => Constructible HashTableIter tag where
        new _ attrs = do
            o <- newZeroHashTableIter
            GI.Attributes.set o attrs
            return o

    -- | A convenience alias for `Nothing` :: `Maybe` `HashTableIter`.
    noHashTableIter :: Maybe HashTableIter
    noHashTableIter = Nothing

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

    -- method HashTableIter::init
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "iter", argType = TInterface (Name {namespace = "GLib", name = "HashTableIter"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "an uninitialized #GHashTableIter", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "hash_table", argType = TGHash (TBasicType TPtr) (TBasicType TPtr), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GHashTable", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Nothing
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_hash_table_iter_init" g_hash_table_iter_init ::
        Ptr HashTableIter ->                    -- iter : TInterface (Name {namespace = "GLib", name = "HashTableIter"})
        Ptr (GHashTable (Ptr ()) (Ptr ())) ->   -- hash_table : TGHash (TBasicType TPtr) (TBasicType TPtr)
        IO ()

    {- |
    Initializes a key\/value pair iterator and associates it with
    /@hashTable@/. Modifying the hash table after calling this function
    invalidates the returned iterator.

    === /C code/
    >
    >GHashTableIter iter;
    >gpointer key, value;
    >
    >g_hash_table_iter_init (&iter, hash_table);
    >while (g_hash_table_iter_next (&iter, &key, &value))
    >  {
    >    // do something with key and value
    >  }

    /Since: 2.16/
    -}
    hashTableIterInit ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        HashTableIter
        {- ^ /@iter@/: an uninitialized 'GI.GLib.Structs.HashTableIter.HashTableIter' -}
        -> Map.Map (Ptr ()) (Ptr ())
        {- ^ /@hashTable@/: a 'GI.GLib.Structs.HashTable.HashTable' -}
        -> m ()
    hashTableIterInit iter hashTable = liftIO $ do
        iter' <- unsafeManagedPtrGetPtr iter
        let hashTable' = Map.toList hashTable
        let hashTable'' = mapFirst ptrPackPtr hashTable'
        let hashTable''' = mapSecond ptrPackPtr hashTable''
        hashTable'''' <- packGHashTable gDirectHash gDirectEqual Nothing Nothing hashTable'''
        g_hash_table_iter_init iter' hashTable''''
        touchManagedPtr iter
        unrefGHashTable hashTable''''
        return ()

    #if ENABLE_OVERLOADING
    data HashTableIterInitMethodInfo
    instance (signature ~ (Map.Map (Ptr ()) (Ptr ()) -> m ()), MonadIO m) => O.MethodInfo HashTableIterInitMethodInfo HashTableIter signature where
        overloadedMethod _ = hashTableIterInit

    #endif

    -- method HashTableIter::next
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "iter", argType = TInterface (Name {namespace = "GLib", name = "HashTableIter"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "an initialized #GHashTableIter", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "key", argType = TBasicType TPtr, direction = DirectionOut, mayBeNull = True, argDoc = Documentation {rawDocText = Just "a location to store the key", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferEverything},Arg {argCName = "value", argType = TBasicType TPtr, direction = DirectionOut, mayBeNull = True, argDoc = Documentation {rawDocText = Just "a location to store the value", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferEverything}]
    -- Lengths : []
    -- returnType : Just (TBasicType TBoolean)
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_hash_table_iter_next" g_hash_table_iter_next ::
        Ptr HashTableIter ->                    -- iter : TInterface (Name {namespace = "GLib", name = "HashTableIter"})
        Ptr (Ptr ()) ->                         -- key : TBasicType TPtr
        Ptr (Ptr ()) ->                         -- value : TBasicType TPtr
        IO CInt

    {- |
    Advances /@iter@/ and retrieves the key and\/or value that are now
    pointed to as a result of this advancement. If 'False' is returned,
    /@key@/ and /@value@/ are not set, and the iterator becomes invalid.

    /Since: 2.16/
    -}
    hashTableIterNext ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        HashTableIter
        {- ^ /@iter@/: an initialized 'GI.GLib.Structs.HashTableIter.HashTableIter' -}
        -> m ((Bool, Ptr (), Ptr ()))
        {- ^ __Returns:__ 'False' if the end of the 'GI.GLib.Structs.HashTable.HashTable' has been reached. -}
    hashTableIterNext iter = liftIO $ do
        iter' <- unsafeManagedPtrGetPtr iter
        key <- allocMem :: IO (Ptr (Ptr ()))
        value <- allocMem :: IO (Ptr (Ptr ()))
        result <- g_hash_table_iter_next iter' key value
        let result' = (/= 0) result
        key' <- peek key
        value' <- peek value
        touchManagedPtr iter
        freeMem key
        freeMem value
        return (result', key', value')

    #if ENABLE_OVERLOADING
    data HashTableIterNextMethodInfo
    instance (signature ~ (m ((Bool, Ptr (), Ptr ()))), MonadIO m) => O.MethodInfo HashTableIterNextMethodInfo HashTableIter signature where
        overloadedMethod _ = hashTableIterNext

    #endif

    -- method HashTableIter::remove
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "iter", argType = TInterface (Name {namespace = "GLib", name = "HashTableIter"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "an initialized #GHashTableIter", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Nothing
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_hash_table_iter_remove" g_hash_table_iter_remove ::
        Ptr HashTableIter ->                    -- iter : TInterface (Name {namespace = "GLib", name = "HashTableIter"})
        IO ()

    {- |
    Removes the key\/value pair currently pointed to by the iterator
    from its associated 'GI.GLib.Structs.HashTable.HashTable'. Can only be called after
    'GI.GLib.Structs.HashTableIter.hashTableIterNext' returned 'True', and cannot be called
    more than once for the same key\/value pair.

    If the 'GI.GLib.Structs.HashTable.HashTable' was created using @/g_hash_table_new_full()/@,
    the key and value are freed using the supplied destroy functions,
    otherwise you have to make sure that any dynamically allocated
    values are freed yourself.

    It is safe to continue iterating the 'GI.GLib.Structs.HashTable.HashTable' afterward:

    === /C code/
    >
    >while (g_hash_table_iter_next (&iter, &key, &value))
    >  {
    >    if (condition)
    >      g_hash_table_iter_remove (&iter);
    >  }

    /Since: 2.16/
    -}
    hashTableIterRemove ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        HashTableIter
        {- ^ /@iter@/: an initialized 'GI.GLib.Structs.HashTableIter.HashTableIter' -}
        -> m ()
    hashTableIterRemove iter = liftIO $ do
        iter' <- unsafeManagedPtrGetPtr iter
        g_hash_table_iter_remove iter'
        touchManagedPtr iter
        return ()

    #if ENABLE_OVERLOADING
    data HashTableIterRemoveMethodInfo
    instance (signature ~ (m ()), MonadIO m) => O.MethodInfo HashTableIterRemoveMethodInfo HashTableIter signature where
        overloadedMethod _ = hashTableIterRemove

    #endif

    -- method HashTableIter::replace
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "iter", argType = TInterface (Name {namespace = "GLib", name = "HashTableIter"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "an initialized #GHashTableIter", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "value", argType = TBasicType TPtr, direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "the value to replace with", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Nothing
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_hash_table_iter_replace" g_hash_table_iter_replace ::
        Ptr HashTableIter ->                    -- iter : TInterface (Name {namespace = "GLib", name = "HashTableIter"})
        Ptr () ->                               -- value : TBasicType TPtr
        IO ()

    {- |
    Replaces the value currently pointed to by the iterator
    from its associated 'GI.GLib.Structs.HashTable.HashTable'. Can only be called after
    'GI.GLib.Structs.HashTableIter.hashTableIterNext' returned 'True'.

    If you supplied a /@valueDestroyFunc@/ when creating the
    'GI.GLib.Structs.HashTable.HashTable', the old value is freed using that function.

    /Since: 2.30/
    -}
    hashTableIterReplace ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        HashTableIter
        {- ^ /@iter@/: an initialized 'GI.GLib.Structs.HashTableIter.HashTableIter' -}
        -> Ptr ()
        {- ^ /@value@/: the value to replace with -}
        -> m ()
    hashTableIterReplace iter value = liftIO $ do
        iter' <- unsafeManagedPtrGetPtr iter
        g_hash_table_iter_replace iter' value
        touchManagedPtr iter
        return ()

    #if ENABLE_OVERLOADING
    data HashTableIterReplaceMethodInfo
    instance (signature ~ (Ptr () -> m ()), MonadIO m) => O.MethodInfo HashTableIterReplaceMethodInfo HashTableIter signature where
        overloadedMethod _ = hashTableIterReplace

    #endif

    -- method HashTableIter::steal
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "iter", argType = TInterface (Name {namespace = "GLib", name = "HashTableIter"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "an initialized #GHashTableIter", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Nothing
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_hash_table_iter_steal" g_hash_table_iter_steal ::
        Ptr HashTableIter ->                    -- iter : TInterface (Name {namespace = "GLib", name = "HashTableIter"})
        IO ()

    {- |
    Removes the key\/value pair currently pointed to by the
    iterator from its associated 'GI.GLib.Structs.HashTable.HashTable', without calling
    the key and value destroy functions. Can only be called
    after 'GI.GLib.Structs.HashTableIter.hashTableIterNext' returned 'True', and cannot
    be called more than once for the same key\/value pair.

    /Since: 2.16/
    -}
    hashTableIterSteal ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        HashTableIter
        {- ^ /@iter@/: an initialized 'GI.GLib.Structs.HashTableIter.HashTableIter' -}
        -> m ()
    hashTableIterSteal iter = liftIO $ do
        iter' <- unsafeManagedPtrGetPtr iter
        g_hash_table_iter_steal iter'
        touchManagedPtr iter
        return ()

    #if ENABLE_OVERLOADING
    data HashTableIterStealMethodInfo
    instance (signature ~ (m ()), MonadIO m) => O.MethodInfo HashTableIterStealMethodInfo HashTableIter signature where
        overloadedMethod _ = hashTableIterSteal

    #endif

    #if ENABLE_OVERLOADING
    type family ResolveHashTableIterMethod (t :: Symbol) (o :: *) :: * where
        ResolveHashTableIterMethod "init" o = HashTableIterInitMethodInfo
        ResolveHashTableIterMethod "next" o = HashTableIterNextMethodInfo
        ResolveHashTableIterMethod "remove" o = HashTableIterRemoveMethodInfo
        ResolveHashTableIterMethod "replace" o = HashTableIterReplaceMethodInfo
        ResolveHashTableIterMethod "steal" o = HashTableIterStealMethodInfo
        ResolveHashTableIterMethod l o = O.MethodResolutionFailed l o

    instance (info ~ ResolveHashTableIterMethod t HashTableIter, O.MethodInfo info HashTableIter p) => O.IsLabelProxy t (HashTableIter -> p) where
        fromLabelProxy _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)

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