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

    This class is the base object class for a factory used to create an
    accessible object for a specific GType. The function
    'GI.Atk.Objects.Registry.registrySetFactoryType' is normally called to store in the
    registry the factory type to be used to create an accessible of a
    particular GType.
    -}

    #define ENABLE_OVERLOADING \
           (!defined(__HADDOCK_VERSION__))

    module GI.Atk.Objects.ObjectFactory
        (

    -- * Exported types
        ObjectFactory(..)                       ,
        IsObjectFactory                         ,
        toObjectFactory                         ,
        noObjectFactory                         ,

     -- * Methods
    -- ** createAccessible #method:createAccessible#

    #if ENABLE_OVERLOADING
        ObjectFactoryCreateAccessibleMethodInfo ,
    #endif
        objectFactoryCreateAccessible           ,

    -- ** getAccessibleType #method:getAccessibleType#

    #if ENABLE_OVERLOADING
        ObjectFactoryGetAccessibleTypeMethodInfo,
    #endif
        objectFactoryGetAccessibleType          ,

    -- ** invalidate #method:invalidate#

    #if ENABLE_OVERLOADING
        ObjectFactoryInvalidateMethodInfo       ,
    #endif
        objectFactoryInvalidate                 ,

        ) 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 {-# SOURCE #-} qualified GI.Atk.Objects.Object as Atk.Object
    import qualified GI.GObject.Objects.Object as GObject.Object

    -- | Memory-managed wrapper type.
    newtype ObjectFactory = ObjectFactory (ManagedPtr ObjectFactory)
    foreign import ccall "atk_object_factory_get_type"
        c_atk_object_factory_get_type :: IO GType

    instance GObject ObjectFactory where
        gobjectType _ = c_atk_object_factory_get_type

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

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

    -- | A convenience alias for `Nothing` :: `Maybe` `ObjectFactory`.
    noObjectFactory :: Maybe ObjectFactory
    noObjectFactory = Nothing

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

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

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

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

    #if ENABLE_OVERLOADING
    #endif

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

    #endif

    -- method ObjectFactory::create_accessible
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "factory", argType = TInterface (Name {namespace = "Atk", name = "ObjectFactory"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "The #AtkObjectFactory associated with @obj's\nobject type", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "obj", argType = TInterface (Name {namespace = "GObject", name = "Object"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GObject", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TInterface (Name {namespace = "Atk", name = "Object"}))
    -- throws : False
    -- Skip return : False

    foreign import ccall "atk_object_factory_create_accessible" atk_object_factory_create_accessible ::
        Ptr ObjectFactory ->                    -- factory : TInterface (Name {namespace = "Atk", name = "ObjectFactory"})
        Ptr GObject.Object.Object ->            -- obj : TInterface (Name {namespace = "GObject", name = "Object"})
        IO (Ptr Atk.Object.Object)

    {- |
    Provides an 'GI.Atk.Objects.Object.Object' that implements an accessibility interface
    on behalf of /@obj@/
    -}
    objectFactoryCreateAccessible ::
        (B.CallStack.HasCallStack, MonadIO m, IsObjectFactory a, GObject.Object.IsObject b) =>
        a
        {- ^ /@factory@/: The 'GI.Atk.Objects.ObjectFactory.ObjectFactory' associated with /@obj@/\'s
    object type -}
        -> b
        {- ^ /@obj@/: a 'GI.GObject.Objects.Object.Object' -}
        -> m Atk.Object.Object
        {- ^ __Returns:__ an 'GI.Atk.Objects.Object.Object' that implements an accessibility
    interface on behalf of /@obj@/ -}
    objectFactoryCreateAccessible factory obj = liftIO $ do
        factory' <- unsafeManagedPtrCastPtr factory
        obj' <- unsafeManagedPtrCastPtr obj
        result <- atk_object_factory_create_accessible factory' obj'
        checkUnexpectedReturnNULL "objectFactoryCreateAccessible" result
        result' <- (wrapObject Atk.Object.Object) result
        touchManagedPtr factory
        touchManagedPtr obj
        return result'

    #if ENABLE_OVERLOADING
    data ObjectFactoryCreateAccessibleMethodInfo
    instance (signature ~ (b -> m Atk.Object.Object), MonadIO m, IsObjectFactory a, GObject.Object.IsObject b) => O.MethodInfo ObjectFactoryCreateAccessibleMethodInfo a signature where
        overloadedMethod _ = objectFactoryCreateAccessible

    #endif

    -- method ObjectFactory::get_accessible_type
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "factory", argType = TInterface (Name {namespace = "Atk", name = "ObjectFactory"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "an #AtkObjectFactory", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TBasicType TGType)
    -- throws : False
    -- Skip return : False

    foreign import ccall "atk_object_factory_get_accessible_type" atk_object_factory_get_accessible_type ::
        Ptr ObjectFactory ->                    -- factory : TInterface (Name {namespace = "Atk", name = "ObjectFactory"})
        IO CGType

    {- |
    Gets the GType of the accessible which is created by the factory.
    -}
    objectFactoryGetAccessibleType ::
        (B.CallStack.HasCallStack, MonadIO m, IsObjectFactory a) =>
        a
        {- ^ /@factory@/: an 'GI.Atk.Objects.ObjectFactory.ObjectFactory' -}
        -> m GType
        {- ^ __Returns:__ the type of the accessible which is created by the /@factory@/.
    The value G_TYPE_INVALID is returned if no type if found. -}
    objectFactoryGetAccessibleType factory = liftIO $ do
        factory' <- unsafeManagedPtrCastPtr factory
        result <- atk_object_factory_get_accessible_type factory'
        let result' = GType result
        touchManagedPtr factory
        return result'

    #if ENABLE_OVERLOADING
    data ObjectFactoryGetAccessibleTypeMethodInfo
    instance (signature ~ (m GType), MonadIO m, IsObjectFactory a) => O.MethodInfo ObjectFactoryGetAccessibleTypeMethodInfo a signature where
        overloadedMethod _ = objectFactoryGetAccessibleType

    #endif

    -- method ObjectFactory::invalidate
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "factory", argType = TInterface (Name {namespace = "Atk", name = "ObjectFactory"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "an #AtkObjectFactory to invalidate", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Nothing
    -- throws : False
    -- Skip return : False

    foreign import ccall "atk_object_factory_invalidate" atk_object_factory_invalidate ::
        Ptr ObjectFactory ->                    -- factory : TInterface (Name {namespace = "Atk", name = "ObjectFactory"})
        IO ()

    {- |
    Inform /@factory@/ that it is no longer being used to create
    accessibles. When called, /@factory@/ may need to inform
    @/AtkObjects/@ which it has created that they need to be re-instantiated.
    Note: primarily used for runtime replacement of @/AtkObjectFactorys/@
    in object registries.
    -}
    objectFactoryInvalidate ::
        (B.CallStack.HasCallStack, MonadIO m, IsObjectFactory a) =>
        a
        {- ^ /@factory@/: an 'GI.Atk.Objects.ObjectFactory.ObjectFactory' to invalidate -}
        -> m ()
    objectFactoryInvalidate factory = liftIO $ do
        factory' <- unsafeManagedPtrCastPtr factory
        atk_object_factory_invalidate factory'
        touchManagedPtr factory
        return ()

    #if ENABLE_OVERLOADING
    data ObjectFactoryInvalidateMethodInfo
    instance (signature ~ (m ()), MonadIO m, IsObjectFactory a) => O.MethodInfo ObjectFactoryInvalidateMethodInfo a signature where
        overloadedMethod _ = objectFactoryInvalidate

    #endif