{- |
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 @GSourceFuncs@ struct contains a table of
functions used to handle event sources in a generic manner.

For idle sources, the prepare and check functions always return 'True'
to indicate that the source is always ready to be processed. The prepare
function also returns a timeout value of 0 to ensure that the @/poll()/@ call
doesn\'t block (since that would be time wasted which could have been spent
running the idle function).

For timeout sources, the prepare and check functions both return 'True'
if the timeout interval has expired. The prepare function also returns
a timeout value to ensure that the @/poll()/@ call doesn\'t block too long
and miss the next timeout.

For file descriptor sources, the prepare function typically returns 'False',
since it must wait until @/poll()/@ has been called before it knows whether
any events need to be processed. It sets the returned timeout to -1 to
indicate that it doesn\'t mind how long the @/poll()/@ call blocks. In the
check function, it tests the results of the @/poll()/@ call to see if the
required condition has been met, and returns 'True' if so.
-}

module GI.GLib.Structs.SourceFuncs
    ( 

-- * Exported types
    SourceFuncs(..)                         ,
    newZeroSourceFuncs                      ,
    noSourceFuncs                           ,


 -- * Properties
-- ** check #attr:check#
    clearSourceFuncsCheck                   ,
    getSourceFuncsCheck                     ,
    setSourceFuncsCheck                     ,
#ifdef ENABLE_OVERLOADING
    sourceFuncs_check                       ,
#endif


-- ** finalize #attr:finalize#
    clearSourceFuncsFinalize                ,
    getSourceFuncsFinalize                  ,
    setSourceFuncsFinalize                  ,
#ifdef ENABLE_OVERLOADING
    sourceFuncs_finalize                    ,
#endif


-- ** prepare #attr:prepare#
    clearSourceFuncsPrepare                 ,
    getSourceFuncsPrepare                   ,
    setSourceFuncsPrepare                   ,
#ifdef ENABLE_OVERLOADING
    sourceFuncs_prepare                     ,
#endif




    ) 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.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.GLib.Callbacks as GLib.Callbacks

newtype SourceFuncs = SourceFuncs (ManagedPtr SourceFuncs)
instance WrappedPtr SourceFuncs where
    wrappedPtrCalloc = callocBytes 48
    wrappedPtrCopy = \p -> withManagedPtr p (copyBytes 48 >=> wrapPtr SourceFuncs)
    wrappedPtrFree = Just ptr_to_g_free

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

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


noSourceFuncs :: Maybe SourceFuncs
noSourceFuncs = Nothing

getSourceFuncsPrepare :: MonadIO m => SourceFuncs -> m (Maybe GLib.Callbacks.SourceFuncsPrepareFieldCallback)
getSourceFuncsPrepare s = liftIO $ withManagedPtr s $ \ptr -> do
    val <- peek (ptr `plusPtr` 0) :: IO (FunPtr GLib.Callbacks.C_SourceFuncsPrepareFieldCallback)
    result <- SP.convertFunPtrIfNonNull val $ \val' -> do
        let val'' = GLib.Callbacks.dynamic_SourceFuncsPrepareFieldCallback val'
        return val''
    return result

setSourceFuncsPrepare :: MonadIO m => SourceFuncs -> FunPtr GLib.Callbacks.C_SourceFuncsPrepareFieldCallback -> m ()
setSourceFuncsPrepare s val = liftIO $ withManagedPtr s $ \ptr -> do
    poke (ptr `plusPtr` 0) (val :: FunPtr GLib.Callbacks.C_SourceFuncsPrepareFieldCallback)

clearSourceFuncsPrepare :: MonadIO m => SourceFuncs -> m ()
clearSourceFuncsPrepare s = liftIO $ withManagedPtr s $ \ptr -> do
    poke (ptr `plusPtr` 0) (FP.nullFunPtr :: FunPtr GLib.Callbacks.C_SourceFuncsPrepareFieldCallback)

#ifdef ENABLE_OVERLOADING
data SourceFuncsPrepareFieldInfo
instance AttrInfo SourceFuncsPrepareFieldInfo where
    type AttrAllowedOps SourceFuncsPrepareFieldInfo = '[ 'AttrSet, 'AttrGet, 'AttrClear]
    type AttrSetTypeConstraint SourceFuncsPrepareFieldInfo = (~) (FunPtr GLib.Callbacks.C_SourceFuncsPrepareFieldCallback)
    type AttrBaseTypeConstraint SourceFuncsPrepareFieldInfo = (~) SourceFuncs
    type AttrGetType SourceFuncsPrepareFieldInfo = Maybe GLib.Callbacks.SourceFuncsPrepareFieldCallback
    type AttrLabel SourceFuncsPrepareFieldInfo = "prepare"
    type AttrOrigin SourceFuncsPrepareFieldInfo = SourceFuncs
    attrGet _ = getSourceFuncsPrepare
    attrSet _ = setSourceFuncsPrepare
    attrConstruct = undefined
    attrClear _ = clearSourceFuncsPrepare

sourceFuncs_prepare :: AttrLabelProxy "prepare"
sourceFuncs_prepare = AttrLabelProxy

#endif


getSourceFuncsCheck :: MonadIO m => SourceFuncs -> m (Maybe GLib.Callbacks.SourceFuncsCheckFieldCallback)
getSourceFuncsCheck s = liftIO $ withManagedPtr s $ \ptr -> do
    val <- peek (ptr `plusPtr` 8) :: IO (FunPtr GLib.Callbacks.C_SourceFuncsCheckFieldCallback)
    result <- SP.convertFunPtrIfNonNull val $ \val' -> do
        let val'' = GLib.Callbacks.dynamic_SourceFuncsCheckFieldCallback val'
        return val''
    return result

setSourceFuncsCheck :: MonadIO m => SourceFuncs -> FunPtr GLib.Callbacks.C_SourceFuncsCheckFieldCallback -> m ()
setSourceFuncsCheck s val = liftIO $ withManagedPtr s $ \ptr -> do
    poke (ptr `plusPtr` 8) (val :: FunPtr GLib.Callbacks.C_SourceFuncsCheckFieldCallback)

clearSourceFuncsCheck :: MonadIO m => SourceFuncs -> m ()
clearSourceFuncsCheck s = liftIO $ withManagedPtr s $ \ptr -> do
    poke (ptr `plusPtr` 8) (FP.nullFunPtr :: FunPtr GLib.Callbacks.C_SourceFuncsCheckFieldCallback)

#ifdef ENABLE_OVERLOADING
data SourceFuncsCheckFieldInfo
instance AttrInfo SourceFuncsCheckFieldInfo where
    type AttrAllowedOps SourceFuncsCheckFieldInfo = '[ 'AttrSet, 'AttrGet, 'AttrClear]
    type AttrSetTypeConstraint SourceFuncsCheckFieldInfo = (~) (FunPtr GLib.Callbacks.C_SourceFuncsCheckFieldCallback)
    type AttrBaseTypeConstraint SourceFuncsCheckFieldInfo = (~) SourceFuncs
    type AttrGetType SourceFuncsCheckFieldInfo = Maybe GLib.Callbacks.SourceFuncsCheckFieldCallback
    type AttrLabel SourceFuncsCheckFieldInfo = "check"
    type AttrOrigin SourceFuncsCheckFieldInfo = SourceFuncs
    attrGet _ = getSourceFuncsCheck
    attrSet _ = setSourceFuncsCheck
    attrConstruct = undefined
    attrClear _ = clearSourceFuncsCheck

sourceFuncs_check :: AttrLabelProxy "check"
sourceFuncs_check = AttrLabelProxy

#endif


getSourceFuncsFinalize :: MonadIO m => SourceFuncs -> m (Maybe GLib.Callbacks.SourceFuncsFinalizeFieldCallback)
getSourceFuncsFinalize s = liftIO $ withManagedPtr s $ \ptr -> do
    val <- peek (ptr `plusPtr` 24) :: IO (FunPtr GLib.Callbacks.C_SourceFuncsFinalizeFieldCallback)
    result <- SP.convertFunPtrIfNonNull val $ \val' -> do
        let val'' = GLib.Callbacks.dynamic_SourceFuncsFinalizeFieldCallback val'
        return val''
    return result

setSourceFuncsFinalize :: MonadIO m => SourceFuncs -> FunPtr GLib.Callbacks.C_SourceFuncsFinalizeFieldCallback -> m ()
setSourceFuncsFinalize s val = liftIO $ withManagedPtr s $ \ptr -> do
    poke (ptr `plusPtr` 24) (val :: FunPtr GLib.Callbacks.C_SourceFuncsFinalizeFieldCallback)

clearSourceFuncsFinalize :: MonadIO m => SourceFuncs -> m ()
clearSourceFuncsFinalize s = liftIO $ withManagedPtr s $ \ptr -> do
    poke (ptr `plusPtr` 24) (FP.nullFunPtr :: FunPtr GLib.Callbacks.C_SourceFuncsFinalizeFieldCallback)

#ifdef ENABLE_OVERLOADING
data SourceFuncsFinalizeFieldInfo
instance AttrInfo SourceFuncsFinalizeFieldInfo where
    type AttrAllowedOps SourceFuncsFinalizeFieldInfo = '[ 'AttrSet, 'AttrGet, 'AttrClear]
    type AttrSetTypeConstraint SourceFuncsFinalizeFieldInfo = (~) (FunPtr GLib.Callbacks.C_SourceFuncsFinalizeFieldCallback)
    type AttrBaseTypeConstraint SourceFuncsFinalizeFieldInfo = (~) SourceFuncs
    type AttrGetType SourceFuncsFinalizeFieldInfo = Maybe GLib.Callbacks.SourceFuncsFinalizeFieldCallback
    type AttrLabel SourceFuncsFinalizeFieldInfo = "finalize"
    type AttrOrigin SourceFuncsFinalizeFieldInfo = SourceFuncs
    attrGet _ = getSourceFuncsFinalize
    attrSet _ = setSourceFuncsFinalize
    attrConstruct = undefined
    attrClear _ = clearSourceFuncsFinalize

sourceFuncs_finalize :: AttrLabelProxy "finalize"
sourceFuncs_finalize = AttrLabelProxy

#endif



#ifdef ENABLE_OVERLOADING
instance O.HasAttributeList SourceFuncs
type instance O.AttributeList SourceFuncs = SourceFuncsAttributeList
type SourceFuncsAttributeList = ('[ '("prepare", SourceFuncsPrepareFieldInfo), '("check", SourceFuncsCheckFieldInfo), '("finalize", SourceFuncsFinalizeFieldInfo)] :: [(Symbol, *)])
#endif

#ifdef ENABLE_OVERLOADING
type family ResolveSourceFuncsMethod (t :: Symbol) (o :: *) :: * where
    ResolveSourceFuncsMethod l o = O.MethodResolutionFailed l o

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

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