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

A 'GI.GObject.Structs.ParamSpecPool.ParamSpecPool' maintains a collection of @/GParamSpecs/@ which can be
quickly accessed by owner and name. The implementation of the 'GI.GObject.Objects.Object.Object' property
system uses such a pool to store the @/GParamSpecs/@ of the properties all object
types.
-}

#define ENABLE_OVERLOADING (MIN_VERSION_haskell_gi_overloading(1,0,0) \
       && !defined(__HADDOCK_VERSION__))

module GI.GObject.Structs.ParamSpecPool
    (

-- * Exported types
    ParamSpecPool(..)                       ,
    noParamSpecPool                         ,


 -- * Methods
-- ** insert #method:insert#

#if ENABLE_OVERLOADING
    ParamSpecPoolInsertMethodInfo           ,
#endif
    paramSpecPoolInsert                     ,


-- ** listOwned #method:listOwned#

#if ENABLE_OVERLOADING
    ParamSpecPoolListOwnedMethodInfo        ,
#endif
    paramSpecPoolListOwned                  ,


-- ** lookup #method:lookup#

#if ENABLE_OVERLOADING
    ParamSpecPoolLookupMethodInfo           ,
#endif
    paramSpecPoolLookup                     ,


-- ** new #method:new#

    paramSpecPoolNew                        ,


-- ** remove #method:remove#

#if ENABLE_OVERLOADING
    ParamSpecPoolRemoveMethodInfo           ,
#endif
    paramSpecPoolRemove                     ,




    ) 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.GClosure as B.GClosure
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.GI.Base.Properties as B.Properties
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 GHC.OverloadedLabels as OL


-- | Memory-managed wrapper type.
newtype ParamSpecPool = ParamSpecPool (ManagedPtr ParamSpecPool)
-- XXX Wrapping a foreign struct/union with no known destructor or size, leak?
instance WrappedPtr ParamSpecPool where
    wrappedPtrCalloc = return nullPtr
    wrappedPtrCopy = return
    wrappedPtrFree = Nothing

-- | A convenience alias for `Nothing` :: `Maybe` `ParamSpecPool`.
noParamSpecPool :: Maybe ParamSpecPool
noParamSpecPool = Nothing


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

-- method ParamSpecPool::insert
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "pool", argType = TInterface (Name {namespace = "GObject", name = "ParamSpecPool"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GParamSpecPool.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "pspec", argType = TParamSpec, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the #GParamSpec to insert", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "owner_type", argType = TBasicType TGType, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GType identifying the owner of @pspec", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_param_spec_pool_insert" g_param_spec_pool_insert ::
    Ptr ParamSpecPool ->                    -- pool : TInterface (Name {namespace = "GObject", name = "ParamSpecPool"})
    Ptr GParamSpec ->                       -- pspec : TParamSpec
    CGType ->                               -- owner_type : TBasicType TGType
    IO ()

{- |
Inserts a 'GI.GObject.Objects.ParamSpec.ParamSpec' in the pool.
-}
paramSpecPoolInsert ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    ParamSpecPool
    {- ^ /@pool@/: a 'GI.GObject.Structs.ParamSpecPool.ParamSpecPool'. -}
    -> GParamSpec
    {- ^ /@pspec@/: the 'GI.GObject.Objects.ParamSpec.ParamSpec' to insert -}
    -> GType
    {- ^ /@ownerType@/: a 'GType' identifying the owner of /@pspec@/ -}
    -> m ()
paramSpecPoolInsert pool pspec ownerType = liftIO $ do
    pool' <- unsafeManagedPtrGetPtr pool
    pspec' <- unsafeManagedPtrGetPtr pspec
    let ownerType' = gtypeToCGType ownerType
    g_param_spec_pool_insert pool' pspec' ownerType'
    touchManagedPtr pool
    touchManagedPtr pspec
    return ()

#if ENABLE_OVERLOADING
data ParamSpecPoolInsertMethodInfo
instance (signature ~ (GParamSpec -> GType -> m ()), MonadIO m) => O.MethodInfo ParamSpecPoolInsertMethodInfo ParamSpecPool signature where
    overloadedMethod _ = paramSpecPoolInsert

#endif

-- XXX Could not generate method ParamSpecPool::list
-- Error was : Not implemented: "unpackCArray : Don't know how to unpack C Array of type TParamSpec"
-- method ParamSpecPool::list_owned
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "pool", argType = TInterface (Name {namespace = "GObject", name = "ParamSpecPool"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GParamSpecPool", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "owner_type", argType = TBasicType TGType, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the owner to look for", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TGList TParamSpec)
-- throws : False
-- Skip return : False

foreign import ccall "g_param_spec_pool_list_owned" g_param_spec_pool_list_owned ::
    Ptr ParamSpecPool ->                    -- pool : TInterface (Name {namespace = "GObject", name = "ParamSpecPool"})
    CGType ->                               -- owner_type : TBasicType TGType
    IO (Ptr (GList (Ptr GParamSpec)))

{- |
Gets an 'GI.GLib.Structs.List.List' of all @/GParamSpecs/@ owned by /@ownerType@/ in
the pool.
-}
paramSpecPoolListOwned ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    ParamSpecPool
    {- ^ /@pool@/: a 'GI.GObject.Structs.ParamSpecPool.ParamSpecPool' -}
    -> GType
    {- ^ /@ownerType@/: the owner to look for -}
    -> m [GParamSpec]
    {- ^ __Returns:__ a
         'GI.GLib.Structs.List.List' of all @/GParamSpecs/@ owned by /@ownerType@/ in
         the pool@/GParamSpecs/@. -}
paramSpecPoolListOwned pool ownerType = liftIO $ do
    pool' <- unsafeManagedPtrGetPtr pool
    let ownerType' = gtypeToCGType ownerType
    result <- g_param_spec_pool_list_owned pool' ownerType'
    result' <- unpackGList result
    result'' <- mapM B.GParamSpec.newGParamSpecFromPtr result'
    g_list_free result
    touchManagedPtr pool
    return result''

#if ENABLE_OVERLOADING
data ParamSpecPoolListOwnedMethodInfo
instance (signature ~ (GType -> m [GParamSpec]), MonadIO m) => O.MethodInfo ParamSpecPoolListOwnedMethodInfo ParamSpecPool signature where
    overloadedMethod _ = paramSpecPoolListOwned

#endif

-- method ParamSpecPool::lookup
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "pool", argType = TInterface (Name {namespace = "GObject", name = "ParamSpecPool"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GParamSpecPool", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "param_name", argType = TBasicType TUTF8, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the name to look for", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "owner_type", argType = TBasicType TGType, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the owner to look for", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "walk_ancestors", argType = TBasicType TBoolean, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "If %TRUE, also try to find a #GParamSpec with @param_name\n owned by an ancestor of @owner_type.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just TParamSpec
-- throws : False
-- Skip return : False

foreign import ccall "g_param_spec_pool_lookup" g_param_spec_pool_lookup ::
    Ptr ParamSpecPool ->                    -- pool : TInterface (Name {namespace = "GObject", name = "ParamSpecPool"})
    CString ->                              -- param_name : TBasicType TUTF8
    CGType ->                               -- owner_type : TBasicType TGType
    CInt ->                                 -- walk_ancestors : TBasicType TBoolean
    IO (Ptr GParamSpec)

{- |
Looks up a 'GI.GObject.Objects.ParamSpec.ParamSpec' in the pool.
-}
paramSpecPoolLookup ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    ParamSpecPool
    {- ^ /@pool@/: a 'GI.GObject.Structs.ParamSpecPool.ParamSpecPool' -}
    -> T.Text
    {- ^ /@paramName@/: the name to look for -}
    -> GType
    {- ^ /@ownerType@/: the owner to look for -}
    -> Bool
    {- ^ /@walkAncestors@/: If 'True', also try to find a 'GI.GObject.Objects.ParamSpec.ParamSpec' with /@paramName@/
 owned by an ancestor of /@ownerType@/. -}
    -> m GParamSpec
    {- ^ __Returns:__ The found 'GI.GObject.Objects.ParamSpec.ParamSpec', or 'Nothing' if no
matching 'GI.GObject.Objects.ParamSpec.ParamSpec' was found. -}
paramSpecPoolLookup pool paramName ownerType walkAncestors = liftIO $ do
    pool' <- unsafeManagedPtrGetPtr pool
    paramName' <- textToCString paramName
    let ownerType' = gtypeToCGType ownerType
    let walkAncestors' = (fromIntegral . fromEnum) walkAncestors
    result <- g_param_spec_pool_lookup pool' paramName' ownerType' walkAncestors'
    checkUnexpectedReturnNULL "paramSpecPoolLookup" result
    result' <- B.GParamSpec.newGParamSpecFromPtr result
    touchManagedPtr pool
    freeMem paramName'
    return result'

#if ENABLE_OVERLOADING
data ParamSpecPoolLookupMethodInfo
instance (signature ~ (T.Text -> GType -> Bool -> m GParamSpec), MonadIO m) => O.MethodInfo ParamSpecPoolLookupMethodInfo ParamSpecPool signature where
    overloadedMethod _ = paramSpecPoolLookup

#endif

-- method ParamSpecPool::remove
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "pool", argType = TInterface (Name {namespace = "GObject", name = "ParamSpecPool"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GParamSpecPool", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "pspec", argType = TParamSpec, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the #GParamSpec to remove", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_param_spec_pool_remove" g_param_spec_pool_remove ::
    Ptr ParamSpecPool ->                    -- pool : TInterface (Name {namespace = "GObject", name = "ParamSpecPool"})
    Ptr GParamSpec ->                       -- pspec : TParamSpec
    IO ()

{- |
Removes a 'GI.GObject.Objects.ParamSpec.ParamSpec' from the pool.
-}
paramSpecPoolRemove ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    ParamSpecPool
    {- ^ /@pool@/: a 'GI.GObject.Structs.ParamSpecPool.ParamSpecPool' -}
    -> GParamSpec
    {- ^ /@pspec@/: the 'GI.GObject.Objects.ParamSpec.ParamSpec' to remove -}
    -> m ()
paramSpecPoolRemove pool pspec = liftIO $ do
    pool' <- unsafeManagedPtrGetPtr pool
    pspec' <- unsafeManagedPtrGetPtr pspec
    g_param_spec_pool_remove pool' pspec'
    touchManagedPtr pool
    touchManagedPtr pspec
    return ()

#if ENABLE_OVERLOADING
data ParamSpecPoolRemoveMethodInfo
instance (signature ~ (GParamSpec -> m ()), MonadIO m) => O.MethodInfo ParamSpecPoolRemoveMethodInfo ParamSpecPool signature where
    overloadedMethod _ = paramSpecPoolRemove

#endif

-- method ParamSpecPool::new
-- method type : MemberFunction
-- Args : [Arg {argCName = "type_prefixing", argType = TBasicType TBoolean, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "Whether the pool will support type-prefixed property names.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "GObject", name = "ParamSpecPool"}))
-- throws : False
-- Skip return : False

foreign import ccall "g_param_spec_pool_new" g_param_spec_pool_new ::
    CInt ->                                 -- type_prefixing : TBasicType TBoolean
    IO (Ptr ParamSpecPool)

{- |
Creates a new 'GI.GObject.Structs.ParamSpecPool.ParamSpecPool'.

If /@typePrefixing@/ is 'True', lookups in the newly created pool will
allow to specify the owner as a colon-separated prefix of the
property name, like \"GtkContainer:border-width\". This feature is
deprecated, so you should always set /@typePrefixing@/ to 'False'.
-}
paramSpecPoolNew ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Bool
    {- ^ /@typePrefixing@/: Whether the pool will support type-prefixed property names. -}
    -> m ParamSpecPool
    {- ^ __Returns:__ a newly allocated 'GI.GObject.Structs.ParamSpecPool.ParamSpecPool'. -}
paramSpecPoolNew typePrefixing = liftIO $ do
    let typePrefixing' = (fromIntegral . fromEnum) typePrefixing
    result <- g_param_spec_pool_new typePrefixing'
    checkUnexpectedReturnNULL "paramSpecPoolNew" result
    result' <- (newPtr ParamSpecPool) result
    return result'

#if ENABLE_OVERLOADING
#endif

#if ENABLE_OVERLOADING
type family ResolveParamSpecPoolMethod (t :: Symbol) (o :: *) :: * where
    ResolveParamSpecPoolMethod "insert" o = ParamSpecPoolInsertMethodInfo
    ResolveParamSpecPoolMethod "listOwned" o = ParamSpecPoolListOwnedMethodInfo
    ResolveParamSpecPoolMethod "lookup" o = ParamSpecPoolLookupMethodInfo
    ResolveParamSpecPoolMethod "remove" o = ParamSpecPoolRemoveMethodInfo
    ResolveParamSpecPoolMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveParamSpecPoolMethod t ParamSpecPool, O.MethodInfo info ParamSpecPool p) => OL.IsLabel t (ParamSpecPool -> 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