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

    Provides a base class for implementing asynchronous function results.

    Asynchronous operations are broken up into two separate operations
    which are chained together by a 'GI.Gio.Callbacks.AsyncReadyCallback'. To begin
    an asynchronous operation, provide a 'GI.Gio.Callbacks.AsyncReadyCallback' to the
    asynchronous function. This callback will be triggered when the
    operation has completed, and must be run in a later iteration of
    the [thread-default main context][g-main-context-push-thread-default]
    from where the operation was initiated. It will be passed a
    'GI.Gio.Interfaces.AsyncResult.AsyncResult' instance filled with the details of the operation\'s
    success or failure, the object the asynchronous function was
    started for and any error codes returned. The asynchronous callback
    function is then expected to call the corresponding \"@/_finish()/@\"
    function, passing the object the function was called for, the
    'GI.Gio.Interfaces.AsyncResult.AsyncResult' instance, and (optionally) an /@error@/ to grab any
    error conditions that may have occurred.

    The \"@/_finish()/@\" function for an operation takes the generic result
    (of type 'GI.Gio.Interfaces.AsyncResult.AsyncResult') and returns the specific result that the
    operation in question yields (e.g. a 'GI.Gio.Objects.FileEnumerator.FileEnumerator' for a
    \"enumerate children\" operation). If the result or error status of the
    operation is not needed, there is no need to call the \"@/_finish()/@\"
    function; GIO will take care of cleaning up the result and error
    information after the 'GI.Gio.Callbacks.AsyncReadyCallback' returns. You can pass
    'Nothing' for the 'GI.Gio.Callbacks.AsyncReadyCallback' if you don\'t need to take any
    action at all after the operation completes. Applications may also
    take a reference to the 'GI.Gio.Interfaces.AsyncResult.AsyncResult' and call \"@/_finish()/@\" later;
    however, the \"@/_finish()/@\" function may be called at most once.

    Example of a typical asynchronous operation flow:

    === /C code/
    >
    >void _theoretical_frobnitz_async (Theoretical         *t,
    >                                  GCancellable        *c,
    >                                  GAsyncReadyCallback  cb,
    >                                  gpointer             u);
    >
    >gboolean _theoretical_frobnitz_finish (Theoretical   *t,
    >                                       GAsyncResult  *res,
    >                                       GError       **e);
    >
    >static void
    >frobnitz_result_func (GObject      *source_object,
    >		 GAsyncResult *res,
    >		 gpointer      user_data)
    >{
    >  gboolean success = FALSE;
    >
    >  success = _theoretical_frobnitz_finish (source_object, res, NULL);
    >
    >  if (success)
    >    g_printf ("Hurray!\n");
    >  else
    >    g_printf ("Uh oh!\n");
    >
    >  ...
    >
    >}
    >
    >int main (int argc, void *argv[])
    >{
    >   ...
    >
    >   _theoretical_frobnitz_async (theoretical_data,
    >                                NULL,
    >                                frobnitz_result_func,
    >                                NULL);
    >
    >   ...
    >}

    The callback for an asynchronous operation is called only once, and is
    always called, even in the case of a cancelled operation. On cancellation
    the result is a 'GI.Gio.Enums.IOErrorEnumCancelled' error.

    ## I\/O Priority # {@/io/@-priority}

    Many I\/O-related asynchronous operations have a priority parameter,
    which is used in certain cases to determine the order in which
    operations are executed. They are not used to determine system-wide
    I\/O scheduling. Priorities are integers, with lower numbers indicating
    higher priority. It is recommended to choose priorities between
    'GI.GLib.Constants.PRIORITY_LOW' and 'GI.GLib.Constants.PRIORITY_HIGH', with 'GI.GLib.Constants.PRIORITY_DEFAULT'
    as a default.
    -}

    #define ENABLE_OVERLOADING \
           (!defined(__HADDOCK_VERSION__))

    module GI.Gio.Interfaces.AsyncResult
        (

    -- * Exported types
        AsyncResult(..)                         ,
        noAsyncResult                           ,
        IsAsyncResult                           ,
        toAsyncResult                           ,

     -- * Methods
    -- ** getSourceObject #method:getSourceObject#

    #if ENABLE_OVERLOADING
        AsyncResultGetSourceObjectMethodInfo    ,
    #endif
        asyncResultGetSourceObject              ,

    -- ** getUserData #method:getUserData#

    #if ENABLE_OVERLOADING
        AsyncResultGetUserDataMethodInfo        ,
    #endif
        asyncResultGetUserData                  ,

    -- ** isTagged #method:isTagged#

    #if ENABLE_OVERLOADING
        AsyncResultIsTaggedMethodInfo           ,
    #endif
        asyncResultIsTagged                     ,

    -- ** legacyPropagateError #method:legacyPropagateError#

    #if ENABLE_OVERLOADING
        AsyncResultLegacyPropagateErrorMethodInfo,
    #endif
        asyncResultLegacyPropagateError         ,

        ) 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

    import qualified GI.GObject.Objects.Object as GObject.Object

    -- interface AsyncResult
    -- | Memory-managed wrapper type.
    newtype AsyncResult = AsyncResult (ManagedPtr AsyncResult)
    -- | A convenience alias for `Nothing` :: `Maybe` `AsyncResult`.
    noAsyncResult :: Maybe AsyncResult
    noAsyncResult = Nothing

    #if ENABLE_OVERLOADING
    type instance O.SignalList AsyncResult = AsyncResultSignalList
    type AsyncResultSignalList = ('[ '("notify", GObject.Object.ObjectNotifySignalInfo)] :: [(Symbol, *)])

    #endif

    foreign import ccall "g_async_result_get_type"
        c_g_async_result_get_type :: IO GType

    instance GObject AsyncResult where
        gobjectType _ = c_g_async_result_get_type

    -- | Type class for types which can be safely cast to `AsyncResult`, for instance with `toAsyncResult`.
    class GObject o => IsAsyncResult o
    #if MIN_VERSION_base(4,9,0)
    instance {-# OVERLAPPABLE #-} (GObject a, O.UnknownAncestorError AsyncResult a) =>
        IsAsyncResult a
    #endif
    instance IsAsyncResult AsyncResult
    instance GObject.Object.IsObject AsyncResult

    -- | Cast to `AsyncResult`, for types for which this is known to be safe. For general casts, use `Data.GI.Base.ManagedPtr.castTo`.
    toAsyncResult :: (MonadIO m, IsAsyncResult o) => o -> m AsyncResult
    toAsyncResult = liftIO . unsafeCastTo AsyncResult

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

    #if ENABLE_OVERLOADING
    #endif

    #if ENABLE_OVERLOADING
    type family ResolveAsyncResultMethod (t :: Symbol) (o :: *) :: * where
        ResolveAsyncResultMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
        ResolveAsyncResultMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
        ResolveAsyncResultMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
        ResolveAsyncResultMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
        ResolveAsyncResultMethod "getv" o = GObject.Object.ObjectGetvMethodInfo
        ResolveAsyncResultMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
        ResolveAsyncResultMethod "isTagged" o = AsyncResultIsTaggedMethodInfo
        ResolveAsyncResultMethod "legacyPropagateError" o = AsyncResultLegacyPropagateErrorMethodInfo
        ResolveAsyncResultMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
        ResolveAsyncResultMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
        ResolveAsyncResultMethod "ref" o = GObject.Object.ObjectRefMethodInfo
        ResolveAsyncResultMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
        ResolveAsyncResultMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
        ResolveAsyncResultMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
        ResolveAsyncResultMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
        ResolveAsyncResultMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
        ResolveAsyncResultMethod "unref" o = GObject.Object.ObjectUnrefMethodInfo
        ResolveAsyncResultMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
        ResolveAsyncResultMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
        ResolveAsyncResultMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
        ResolveAsyncResultMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
        ResolveAsyncResultMethod "getSourceObject" o = AsyncResultGetSourceObjectMethodInfo
        ResolveAsyncResultMethod "getUserData" o = AsyncResultGetUserDataMethodInfo
        ResolveAsyncResultMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
        ResolveAsyncResultMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
        ResolveAsyncResultMethod l o = O.MethodResolutionFailed l o

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

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

    -- method AsyncResult::get_source_object
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "res", argType = TInterface (Name {namespace = "Gio", name = "AsyncResult"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GAsyncResult", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TInterface (Name {namespace = "GObject", name = "Object"}))
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_async_result_get_source_object" g_async_result_get_source_object ::
        Ptr AsyncResult ->                      -- res : TInterface (Name {namespace = "Gio", name = "AsyncResult"})
        IO (Ptr GObject.Object.Object)

    {- |
    Gets the source object from a 'GI.Gio.Interfaces.AsyncResult.AsyncResult'.
    -}
    asyncResultGetSourceObject ::
        (B.CallStack.HasCallStack, MonadIO m, IsAsyncResult a) =>
        a
        {- ^ /@res@/: a 'GI.Gio.Interfaces.AsyncResult.AsyncResult' -}
        -> m (Maybe GObject.Object.Object)
        {- ^ __Returns:__ a new reference to the source
       object for the /@res@/, or 'Nothing' if there is none. -}
    asyncResultGetSourceObject res = liftIO $ do
        res' <- unsafeManagedPtrCastPtr res
        result <- g_async_result_get_source_object res'
        maybeResult <- convertIfNonNull result $ \result' -> do
            result'' <- (wrapObject GObject.Object.Object) result'
            return result''
        touchManagedPtr res
        return maybeResult

    #if ENABLE_OVERLOADING
    data AsyncResultGetSourceObjectMethodInfo
    instance (signature ~ (m (Maybe GObject.Object.Object)), MonadIO m, IsAsyncResult a) => O.MethodInfo AsyncResultGetSourceObjectMethodInfo a signature where
        overloadedMethod _ = asyncResultGetSourceObject

    #endif

    -- method AsyncResult::get_user_data
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "res", argType = TInterface (Name {namespace = "Gio", name = "AsyncResult"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GAsyncResult.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TBasicType TPtr)
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_async_result_get_user_data" g_async_result_get_user_data ::
        Ptr AsyncResult ->                      -- res : TInterface (Name {namespace = "Gio", name = "AsyncResult"})
        IO (Ptr ())

    {- |
    Gets the user data from a 'GI.Gio.Interfaces.AsyncResult.AsyncResult'.
    -}
    asyncResultGetUserData ::
        (B.CallStack.HasCallStack, MonadIO m, IsAsyncResult a) =>
        a
        {- ^ /@res@/: a 'GI.Gio.Interfaces.AsyncResult.AsyncResult'. -}
        -> m (Ptr ())
        {- ^ __Returns:__ the user data for /@res@/. -}
    asyncResultGetUserData res = liftIO $ do
        res' <- unsafeManagedPtrCastPtr res
        result <- g_async_result_get_user_data res'
        touchManagedPtr res
        return result

    #if ENABLE_OVERLOADING
    data AsyncResultGetUserDataMethodInfo
    instance (signature ~ (m (Ptr ())), MonadIO m, IsAsyncResult a) => O.MethodInfo AsyncResultGetUserDataMethodInfo a signature where
        overloadedMethod _ = asyncResultGetUserData

    #endif

    -- method AsyncResult::is_tagged
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "res", argType = TInterface (Name {namespace = "Gio", name = "AsyncResult"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GAsyncResult", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "source_tag", argType = TBasicType TPtr, direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "an application-defined tag", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TBasicType TBoolean)
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_async_result_is_tagged" g_async_result_is_tagged ::
        Ptr AsyncResult ->                      -- res : TInterface (Name {namespace = "Gio", name = "AsyncResult"})
        Ptr () ->                               -- source_tag : TBasicType TPtr
        IO CInt

    {- |
    Checks if /@res@/ has the given /@sourceTag@/ (generally a function
    pointer indicating the function /@res@/ was created by).

    /Since: 2.34/
    -}
    asyncResultIsTagged ::
        (B.CallStack.HasCallStack, MonadIO m, IsAsyncResult a) =>
        a
        {- ^ /@res@/: a 'GI.Gio.Interfaces.AsyncResult.AsyncResult' -}
        -> Ptr ()
        {- ^ /@sourceTag@/: an application-defined tag -}
        -> m Bool
        {- ^ __Returns:__ 'True' if /@res@/ has the indicated /@sourceTag@/, 'False' if
      not. -}
    asyncResultIsTagged res sourceTag = liftIO $ do
        res' <- unsafeManagedPtrCastPtr res
        result <- g_async_result_is_tagged res' sourceTag
        let result' = (/= 0) result
        touchManagedPtr res
        return result'

    #if ENABLE_OVERLOADING
    data AsyncResultIsTaggedMethodInfo
    instance (signature ~ (Ptr () -> m Bool), MonadIO m, IsAsyncResult a) => O.MethodInfo AsyncResultIsTaggedMethodInfo a signature where
        overloadedMethod _ = asyncResultIsTagged

    #endif

    -- method AsyncResult::legacy_propagate_error
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "res", argType = TInterface (Name {namespace = "Gio", name = "AsyncResult"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GAsyncResult", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TBasicType TBoolean)
    -- throws : True
    -- Skip return : False

    foreign import ccall "g_async_result_legacy_propagate_error" g_async_result_legacy_propagate_error ::
        Ptr AsyncResult ->                      -- res : TInterface (Name {namespace = "Gio", name = "AsyncResult"})
        Ptr (Ptr GError) ->                     -- error
        IO CInt

    {- |
    If /@res@/ is a 'GI.Gio.Objects.SimpleAsyncResult.SimpleAsyncResult', this is equivalent to
    'GI.Gio.Objects.SimpleAsyncResult.simpleAsyncResultPropagateError'. Otherwise it returns
    'False'.

    This can be used for legacy error handling in async *@/_finish()/@
    wrapper functions that traditionally handled 'GI.Gio.Objects.SimpleAsyncResult.SimpleAsyncResult'
    error returns themselves rather than calling into the virtual method.
    This should not be used in new code; 'GI.Gio.Interfaces.AsyncResult.AsyncResult' errors that are
    set by virtual methods should also be extracted by virtual methods,
    to enable subclasses to chain up correctly.

    /Since: 2.34/
    -}
    asyncResultLegacyPropagateError ::
        (B.CallStack.HasCallStack, MonadIO m, IsAsyncResult a) =>
        a
        {- ^ /@res@/: a 'GI.Gio.Interfaces.AsyncResult.AsyncResult' -}
        -> m ()
        {- ^ /(Can throw 'Data.GI.Base.GError.GError')/ -}
    asyncResultLegacyPropagateError res = liftIO $ do
        res' <- unsafeManagedPtrCastPtr res
        onException (do
            _ <- propagateGError $ g_async_result_legacy_propagate_error res'
            touchManagedPtr res
            return ()
         ) (do
            return ()
         )

    #if ENABLE_OVERLOADING
    data AsyncResultLegacyPropagateErrorMethodInfo
    instance (signature ~ (m ()), MonadIO m, IsAsyncResult a) => O.MethodInfo AsyncResultLegacyPropagateErrorMethodInfo a signature where
        overloadedMethod _ = asyncResultLegacyPropagateError

    #endif