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

    The 'GI.Gio.Interfaces.DBusObject.DBusObject' type is the base type for D-Bus objects on both
    the service side (see 'GI.Gio.Objects.DBusObjectSkeleton.DBusObjectSkeleton') and the client side
    (see 'GI.Gio.Objects.DBusObjectProxy.DBusObjectProxy'). It is essentially just a container of
    interfaces.
    -}

    #define ENABLE_OVERLOADING \
           (!defined(__HADDOCK_VERSION__))

    module GI.Gio.Interfaces.DBusObject
        (

    -- * Exported types
        DBusObject(..)                          ,
        noDBusObject                            ,
        IsDBusObject                            ,
        toDBusObject                            ,

     -- * Methods
    -- ** getInterface #method:getInterface#

    #if ENABLE_OVERLOADING
        DBusObjectGetInterfaceMethodInfo        ,
    #endif
        dBusObjectGetInterface                  ,

    -- ** getInterfaces #method:getInterfaces#

    #if ENABLE_OVERLOADING
        DBusObjectGetInterfacesMethodInfo       ,
    #endif
        dBusObjectGetInterfaces                 ,

    -- ** getObjectPath #method:getObjectPath#

    #if ENABLE_OVERLOADING
        DBusObjectGetObjectPathMethodInfo       ,
    #endif
        dBusObjectGetObjectPath                 ,

     -- * Signals
    -- ** interfaceAdded #signal:interfaceAdded#

        C_DBusObjectInterfaceAddedCallback      ,
        DBusObjectInterfaceAddedCallback        ,
    #if ENABLE_OVERLOADING
        DBusObjectInterfaceAddedSignalInfo      ,
    #endif
        afterDBusObjectInterfaceAdded           ,
        genClosure_DBusObjectInterfaceAdded     ,
        mk_DBusObjectInterfaceAddedCallback     ,
        noDBusObjectInterfaceAddedCallback      ,
        onDBusObjectInterfaceAdded              ,
        wrap_DBusObjectInterfaceAddedCallback   ,

    -- ** interfaceRemoved #signal:interfaceRemoved#

        C_DBusObjectInterfaceRemovedCallback    ,
        DBusObjectInterfaceRemovedCallback      ,
    #if ENABLE_OVERLOADING
        DBusObjectInterfaceRemovedSignalInfo    ,
    #endif
        afterDBusObjectInterfaceRemoved         ,
        genClosure_DBusObjectInterfaceRemoved   ,
        mk_DBusObjectInterfaceRemovedCallback   ,
        noDBusObjectInterfaceRemovedCallback    ,
        onDBusObjectInterfaceRemoved            ,
        wrap_DBusObjectInterfaceRemovedCallback ,

        ) 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
    import {-# SOURCE #-} qualified GI.Gio.Interfaces.DBusInterface as Gio.DBusInterface

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

    -- signal DBusObject::interface-added
    {- |
    Emitted when /@interface@/ is added to /@object@/.

    /Since: 2.30/
    -}
    type DBusObjectInterfaceAddedCallback =
        Gio.DBusInterface.DBusInterface
        {- ^ /@interface@/: The 'GI.Gio.Interfaces.DBusInterface.DBusInterface' that was added. -}
        -> IO ()

    -- | A convenience synonym for @`Nothing` :: `Maybe` `DBusObjectInterfaceAddedCallback`@.
    noDBusObjectInterfaceAddedCallback :: Maybe DBusObjectInterfaceAddedCallback
    noDBusObjectInterfaceAddedCallback = Nothing

    -- | Type for the callback on the (unwrapped) C side.
    type C_DBusObjectInterfaceAddedCallback =
        Ptr () ->                               -- object
        Ptr Gio.DBusInterface.DBusInterface ->
        Ptr () ->                               -- user_data
        IO ()

    -- | Generate a function pointer callable from C code, from a `C_DBusObjectInterfaceAddedCallback`.
    foreign import ccall "wrapper"
        mk_DBusObjectInterfaceAddedCallback :: C_DBusObjectInterfaceAddedCallback -> IO (FunPtr C_DBusObjectInterfaceAddedCallback)

    -- | Wrap the callback into a `Closure`.
    genClosure_DBusObjectInterfaceAdded :: DBusObjectInterfaceAddedCallback -> IO Closure
    genClosure_DBusObjectInterfaceAdded cb = do
        let cb' = wrap_DBusObjectInterfaceAddedCallback cb
        mk_DBusObjectInterfaceAddedCallback cb' >>= newCClosure

    -- | Wrap a `DBusObjectInterfaceAddedCallback` into a `C_DBusObjectInterfaceAddedCallback`.
    wrap_DBusObjectInterfaceAddedCallback ::
        DBusObjectInterfaceAddedCallback ->
        C_DBusObjectInterfaceAddedCallback
    wrap_DBusObjectInterfaceAddedCallback _cb _ interface _ = do
        interface' <- (newObject Gio.DBusInterface.DBusInterface) interface
        _cb  interface'

    {- |
    Connect a signal handler for the “@interface-added@” signal, to be run before the default handler.
    When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to

    @
    'Data.GI.Base.Signals.on' dBusObject #interfaceAdded callback
    @
    -}
    onDBusObjectInterfaceAdded :: (IsDBusObject a, MonadIO m) => a -> DBusObjectInterfaceAddedCallback -> m SignalHandlerId
    onDBusObjectInterfaceAdded obj cb = liftIO $ do
        let cb' = wrap_DBusObjectInterfaceAddedCallback cb
        cb'' <- mk_DBusObjectInterfaceAddedCallback cb'
        connectSignalFunPtr obj "interface-added" cb'' SignalConnectBefore

    {- |
    Connect a signal handler for the “@interface-added@” signal, to be run after the default handler.
    When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to

    @
    'Data.GI.Base.Signals.after' dBusObject #interfaceAdded callback
    @
    -}
    afterDBusObjectInterfaceAdded :: (IsDBusObject a, MonadIO m) => a -> DBusObjectInterfaceAddedCallback -> m SignalHandlerId
    afterDBusObjectInterfaceAdded obj cb = liftIO $ do
        let cb' = wrap_DBusObjectInterfaceAddedCallback cb
        cb'' <- mk_DBusObjectInterfaceAddedCallback cb'
        connectSignalFunPtr obj "interface-added" cb'' SignalConnectAfter

    -- signal DBusObject::interface-removed
    {- |
    Emitted when /@interface@/ is removed from /@object@/.

    /Since: 2.30/
    -}
    type DBusObjectInterfaceRemovedCallback =
        Gio.DBusInterface.DBusInterface
        {- ^ /@interface@/: The 'GI.Gio.Interfaces.DBusInterface.DBusInterface' that was removed. -}
        -> IO ()

    -- | A convenience synonym for @`Nothing` :: `Maybe` `DBusObjectInterfaceRemovedCallback`@.
    noDBusObjectInterfaceRemovedCallback :: Maybe DBusObjectInterfaceRemovedCallback
    noDBusObjectInterfaceRemovedCallback = Nothing

    -- | Type for the callback on the (unwrapped) C side.
    type C_DBusObjectInterfaceRemovedCallback =
        Ptr () ->                               -- object
        Ptr Gio.DBusInterface.DBusInterface ->
        Ptr () ->                               -- user_data
        IO ()

    -- | Generate a function pointer callable from C code, from a `C_DBusObjectInterfaceRemovedCallback`.
    foreign import ccall "wrapper"
        mk_DBusObjectInterfaceRemovedCallback :: C_DBusObjectInterfaceRemovedCallback -> IO (FunPtr C_DBusObjectInterfaceRemovedCallback)

    -- | Wrap the callback into a `Closure`.
    genClosure_DBusObjectInterfaceRemoved :: DBusObjectInterfaceRemovedCallback -> IO Closure
    genClosure_DBusObjectInterfaceRemoved cb = do
        let cb' = wrap_DBusObjectInterfaceRemovedCallback cb
        mk_DBusObjectInterfaceRemovedCallback cb' >>= newCClosure

    -- | Wrap a `DBusObjectInterfaceRemovedCallback` into a `C_DBusObjectInterfaceRemovedCallback`.
    wrap_DBusObjectInterfaceRemovedCallback ::
        DBusObjectInterfaceRemovedCallback ->
        C_DBusObjectInterfaceRemovedCallback
    wrap_DBusObjectInterfaceRemovedCallback _cb _ interface _ = do
        interface' <- (newObject Gio.DBusInterface.DBusInterface) interface
        _cb  interface'

    {- |
    Connect a signal handler for the “@interface-removed@” signal, to be run before the default handler.
    When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to

    @
    'Data.GI.Base.Signals.on' dBusObject #interfaceRemoved callback
    @
    -}
    onDBusObjectInterfaceRemoved :: (IsDBusObject a, MonadIO m) => a -> DBusObjectInterfaceRemovedCallback -> m SignalHandlerId
    onDBusObjectInterfaceRemoved obj cb = liftIO $ do
        let cb' = wrap_DBusObjectInterfaceRemovedCallback cb
        cb'' <- mk_DBusObjectInterfaceRemovedCallback cb'
        connectSignalFunPtr obj "interface-removed" cb'' SignalConnectBefore

    {- |
    Connect a signal handler for the “@interface-removed@” signal, to be run after the default handler.
    When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to

    @
    'Data.GI.Base.Signals.after' dBusObject #interfaceRemoved callback
    @
    -}
    afterDBusObjectInterfaceRemoved :: (IsDBusObject a, MonadIO m) => a -> DBusObjectInterfaceRemovedCallback -> m SignalHandlerId
    afterDBusObjectInterfaceRemoved obj cb = liftIO $ do
        let cb' = wrap_DBusObjectInterfaceRemovedCallback cb
        cb'' <- mk_DBusObjectInterfaceRemovedCallback cb'
        connectSignalFunPtr obj "interface-removed" cb'' SignalConnectAfter

    #if ENABLE_OVERLOADING
    data DBusObjectInterfaceAddedSignalInfo
    instance SignalInfo DBusObjectInterfaceAddedSignalInfo where
        type HaskellCallbackType DBusObjectInterfaceAddedSignalInfo = DBusObjectInterfaceAddedCallback
        connectSignal _ obj cb connectMode = do
            let cb' = wrap_DBusObjectInterfaceAddedCallback cb
            cb'' <- mk_DBusObjectInterfaceAddedCallback cb'
            connectSignalFunPtr obj "interface-added" cb'' connectMode

    data DBusObjectInterfaceRemovedSignalInfo
    instance SignalInfo DBusObjectInterfaceRemovedSignalInfo where
        type HaskellCallbackType DBusObjectInterfaceRemovedSignalInfo = DBusObjectInterfaceRemovedCallback
        connectSignal _ obj cb connectMode = do
            let cb' = wrap_DBusObjectInterfaceRemovedCallback cb
            cb'' <- mk_DBusObjectInterfaceRemovedCallback cb'
            connectSignalFunPtr obj "interface-removed" cb'' connectMode

    type instance O.SignalList DBusObject = DBusObjectSignalList
    type DBusObjectSignalList = ('[ '("interfaceAdded", DBusObjectInterfaceAddedSignalInfo), '("interfaceRemoved", DBusObjectInterfaceRemovedSignalInfo), '("notify", GObject.Object.ObjectNotifySignalInfo)] :: [(Symbol, *)])

    #endif

    foreign import ccall "g_dbus_object_get_type"
        c_g_dbus_object_get_type :: IO GType

    instance GObject DBusObject where
        gobjectType _ = c_g_dbus_object_get_type

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

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

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

    #if ENABLE_OVERLOADING
    #endif

    #if ENABLE_OVERLOADING
    type family ResolveDBusObjectMethod (t :: Symbol) (o :: *) :: * where
        ResolveDBusObjectMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
        ResolveDBusObjectMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
        ResolveDBusObjectMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
        ResolveDBusObjectMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
        ResolveDBusObjectMethod "getv" o = GObject.Object.ObjectGetvMethodInfo
        ResolveDBusObjectMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
        ResolveDBusObjectMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
        ResolveDBusObjectMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
        ResolveDBusObjectMethod "ref" o = GObject.Object.ObjectRefMethodInfo
        ResolveDBusObjectMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
        ResolveDBusObjectMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
        ResolveDBusObjectMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
        ResolveDBusObjectMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
        ResolveDBusObjectMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
        ResolveDBusObjectMethod "unref" o = GObject.Object.ObjectUnrefMethodInfo
        ResolveDBusObjectMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
        ResolveDBusObjectMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
        ResolveDBusObjectMethod "getInterface" o = DBusObjectGetInterfaceMethodInfo
        ResolveDBusObjectMethod "getInterfaces" o = DBusObjectGetInterfacesMethodInfo
        ResolveDBusObjectMethod "getObjectPath" o = DBusObjectGetObjectPathMethodInfo
        ResolveDBusObjectMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
        ResolveDBusObjectMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
        ResolveDBusObjectMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
        ResolveDBusObjectMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
        ResolveDBusObjectMethod l o = O.MethodResolutionFailed l o

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

    #if MIN_VERSION_base(4,9,0)
    instance (info ~ ResolveDBusObjectMethod t DBusObject, O.MethodInfo info DBusObject p) => O.IsLabel t (DBusObject -> 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 DBusObject::get_interface
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "object", argType = TInterface (Name {namespace = "Gio", name = "DBusObject"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "A #GDBusObject.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "interface_name", argType = TBasicType TUTF8, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "A D-Bus interface name.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TInterface (Name {namespace = "Gio", name = "DBusInterface"}))
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_dbus_object_get_interface" g_dbus_object_get_interface ::
        Ptr DBusObject ->                       -- object : TInterface (Name {namespace = "Gio", name = "DBusObject"})
        CString ->                              -- interface_name : TBasicType TUTF8
        IO (Ptr Gio.DBusInterface.DBusInterface)

    {- |
    Gets the D-Bus interface with name /@interfaceName@/ associated with
    /@object@/, if any.

    /Since: 2.30/
    -}
    dBusObjectGetInterface ::
        (B.CallStack.HasCallStack, MonadIO m, IsDBusObject a) =>
        a
        {- ^ /@object@/: A 'GI.Gio.Interfaces.DBusObject.DBusObject'. -}
        -> T.Text
        {- ^ /@interfaceName@/: A D-Bus interface name. -}
        -> m Gio.DBusInterface.DBusInterface
        {- ^ __Returns:__ 'Nothing' if not found, otherwise a
      'GI.Gio.Interfaces.DBusInterface.DBusInterface' that must be freed with 'GI.GObject.Objects.Object.objectUnref'. -}
    dBusObjectGetInterface object interfaceName = liftIO $ do
        object' <- unsafeManagedPtrCastPtr object
        interfaceName' <- textToCString interfaceName
        result <- g_dbus_object_get_interface object' interfaceName'
        checkUnexpectedReturnNULL "dBusObjectGetInterface" result
        result' <- (wrapObject Gio.DBusInterface.DBusInterface) result
        touchManagedPtr object
        freeMem interfaceName'
        return result'

    #if ENABLE_OVERLOADING
    data DBusObjectGetInterfaceMethodInfo
    instance (signature ~ (T.Text -> m Gio.DBusInterface.DBusInterface), MonadIO m, IsDBusObject a) => O.MethodInfo DBusObjectGetInterfaceMethodInfo a signature where
        overloadedMethod _ = dBusObjectGetInterface

    #endif

    -- method DBusObject::get_interfaces
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "object", argType = TInterface (Name {namespace = "Gio", name = "DBusObject"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "A #GDBusObject.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TGList (TInterface (Name {namespace = "Gio", name = "DBusInterface"})))
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_dbus_object_get_interfaces" g_dbus_object_get_interfaces ::
        Ptr DBusObject ->                       -- object : TInterface (Name {namespace = "Gio", name = "DBusObject"})
        IO (Ptr (GList (Ptr Gio.DBusInterface.DBusInterface)))

    {- |
    Gets the D-Bus interfaces associated with /@object@/.

    /Since: 2.30/
    -}
    dBusObjectGetInterfaces ::
        (B.CallStack.HasCallStack, MonadIO m, IsDBusObject a) =>
        a
        {- ^ /@object@/: A 'GI.Gio.Interfaces.DBusObject.DBusObject'. -}
        -> m [Gio.DBusInterface.DBusInterface]
        {- ^ __Returns:__ A list of 'GI.Gio.Interfaces.DBusInterface.DBusInterface' instances.
      The returned list must be freed by @/g_list_free()/@ after each element has been freed
      with 'GI.GObject.Objects.Object.objectUnref'. -}
    dBusObjectGetInterfaces object = liftIO $ do
        object' <- unsafeManagedPtrCastPtr object
        result <- g_dbus_object_get_interfaces object'
        result' <- unpackGList result
        result'' <- mapM (wrapObject Gio.DBusInterface.DBusInterface) result'
        g_list_free result
        touchManagedPtr object
        return result''

    #if ENABLE_OVERLOADING
    data DBusObjectGetInterfacesMethodInfo
    instance (signature ~ (m [Gio.DBusInterface.DBusInterface]), MonadIO m, IsDBusObject a) => O.MethodInfo DBusObjectGetInterfacesMethodInfo a signature where
        overloadedMethod _ = dBusObjectGetInterfaces

    #endif

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

    foreign import ccall "g_dbus_object_get_object_path" g_dbus_object_get_object_path ::
        Ptr DBusObject ->                       -- object : TInterface (Name {namespace = "Gio", name = "DBusObject"})
        IO CString

    {- |
    Gets the object path for /@object@/.

    /Since: 2.30/
    -}
    dBusObjectGetObjectPath ::
        (B.CallStack.HasCallStack, MonadIO m, IsDBusObject a) =>
        a
        {- ^ /@object@/: A 'GI.Gio.Interfaces.DBusObject.DBusObject'. -}
        -> m T.Text
        {- ^ __Returns:__ A string owned by /@object@/. Do not free. -}
    dBusObjectGetObjectPath object = liftIO $ do
        object' <- unsafeManagedPtrCastPtr object
        result <- g_dbus_object_get_object_path object'
        checkUnexpectedReturnNULL "dBusObjectGetObjectPath" result
        result' <- cstringToText result
        touchManagedPtr object
        return result'

    #if ENABLE_OVERLOADING
    data DBusObjectGetObjectPathMethodInfo
    instance (signature ~ (m T.Text), MonadIO m, IsDBusObject a) => O.MethodInfo DBusObjectGetObjectPathMethodInfo a signature where
        overloadedMethod _ = dBusObjectGetObjectPath

    #endif