{-# LANGUAGE TypeApplications #-}


-- | Copyright  : Will Thompson and Iñaki García Etxebarria
-- License    : LGPL-2.1
-- Maintainer : Iñaki García Etxebarria
-- 
-- @GTimer@ records a start time, and counts microseconds elapsed since
-- that time.
-- 
-- This is done somewhat differently on different platforms, and can be
-- tricky to get exactly right, so @GTimer@ provides a portable\/convenient interface.

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

module GI.GLib.Structs.Timer
    ( 

-- * Exported types
    Timer(..)                               ,


 -- * Methods
-- | 
-- 
--  === __Click to display all available methods, including inherited ones__
-- ==== Methods
-- [continue]("GI.GLib.Structs.Timer#g:method:continue"), [destroy]("GI.GLib.Structs.Timer#g:method:destroy"), [elapsed]("GI.GLib.Structs.Timer#g:method:elapsed"), [isActive]("GI.GLib.Structs.Timer#g:method:isActive"), [reset]("GI.GLib.Structs.Timer#g:method:reset"), [start]("GI.GLib.Structs.Timer#g:method:start"), [stop]("GI.GLib.Structs.Timer#g:method:stop").
-- 
-- ==== Getters
-- /None/.
-- 
-- ==== Setters
-- /None/.

#if defined(ENABLE_OVERLOADING)
    ResolveTimerMethod                      ,
#endif

-- ** continue #method:continue#

#if defined(ENABLE_OVERLOADING)
    TimerContinueMethodInfo                 ,
#endif
    timerContinue                           ,


-- ** destroy #method:destroy#

#if defined(ENABLE_OVERLOADING)
    TimerDestroyMethodInfo                  ,
#endif
    timerDestroy                            ,


-- ** elapsed #method:elapsed#

#if defined(ENABLE_OVERLOADING)
    TimerElapsedMethodInfo                  ,
#endif
    timerElapsed                            ,


-- ** isActive #method:isActive#

#if defined(ENABLE_OVERLOADING)
    TimerIsActiveMethodInfo                 ,
#endif
    timerIsActive                           ,


-- ** reset #method:reset#

#if defined(ENABLE_OVERLOADING)
    TimerResetMethodInfo                    ,
#endif
    timerReset                              ,


-- ** start #method:start#

#if defined(ENABLE_OVERLOADING)
    TimerStartMethodInfo                    ,
#endif
    timerStart                              ,


-- ** stop #method:stop#

#if defined(ENABLE_OVERLOADING)
    TimerStopMethodInfo                     ,
#endif
    timerStop                               ,




    ) 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.BasicTypes as B.Types
import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr
import qualified Data.GI.Base.GArray as B.GArray
import qualified Data.GI.Base.GClosure as B.GClosure
import qualified Data.GI.Base.GError as B.GError
import qualified Data.GI.Base.GHashTable as B.GHT
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.GI.Base.Signals as B.Signals
import qualified Control.Monad.IO.Class as MIO
import qualified Data.Coerce as Coerce
import qualified Data.Text as T
import qualified Data.Kind as DK
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
import qualified GHC.Records as R
import qualified Data.Word as DW
import qualified Data.Int as DI
import qualified System.Posix.Types as SPT
import qualified Foreign.C.Types as FCT

-- Workaround for https://gitlab.haskell.org/ghc/ghc/-/issues/23392
#if MIN_VERSION_base(4,18,0)

#else

#endif

-- | Memory-managed wrapper type.
newtype Timer = Timer (SP.ManagedPtr Timer)
    deriving (Eq)

instance SP.ManagedPtrNewtype Timer where
    toManagedPtr (Timer p) = p

-- XXX Wrapping a foreign struct/union with no known destructor or size, leak?
instance BoxedPtr Timer where
    boxedPtrCopy = return
    boxedPtrFree = \_x -> return ()


#if defined(ENABLE_OVERLOADING)
instance O.HasAttributeList Timer
type instance O.AttributeList Timer = TimerAttributeList
type TimerAttributeList = ('[ ] :: [(Symbol, DK.Type)])
#endif

-- method Timer::continue
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "timer"
--           , argType = TInterface Name { namespace = "GLib" , name = "Timer" }
--           , argCType = Just "GTimer*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GTimer." , sinceVersion = Nothing }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_timer_continue" g_timer_continue :: 
    Ptr Timer ->                            -- timer : TInterface (Name {namespace = "GLib", name = "Timer"})
    IO ()

-- | Resumes a timer that has previously been stopped with
-- 'GI.GLib.Structs.Timer.timerStop'. 'GI.GLib.Structs.Timer.timerStop' must be called before using this
-- function.
-- 
-- /Since: 2.4/
timerContinue ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Timer
    -- ^ /@timer@/: a t'GI.GLib.Structs.Timer.Timer'.
    -> m ()
timerContinue timer = liftIO $ do
    timer' <- unsafeManagedPtrGetPtr timer
    g_timer_continue timer'
    touchManagedPtr timer
    return ()

#if defined(ENABLE_OVERLOADING)
data TimerContinueMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.OverloadedMethod TimerContinueMethodInfo Timer signature where
    overloadedMethod = timerContinue

instance O.OverloadedMethodInfo TimerContinueMethodInfo Timer where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.Timer.timerContinue",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-Timer.html#v:timerContinue"
        })


#endif

-- method Timer::destroy
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "timer"
--           , argType = TInterface Name { namespace = "GLib" , name = "Timer" }
--           , argCType = Just "GTimer*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GTimer to destroy."
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_timer_destroy" g_timer_destroy :: 
    Ptr Timer ->                            -- timer : TInterface (Name {namespace = "GLib", name = "Timer"})
    IO ()

-- | Destroys a timer, freeing associated resources.
timerDestroy ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Timer
    -- ^ /@timer@/: a t'GI.GLib.Structs.Timer.Timer' to destroy.
    -> m ()
timerDestroy timer = liftIO $ do
    timer' <- unsafeManagedPtrGetPtr timer
    g_timer_destroy timer'
    touchManagedPtr timer
    return ()

#if defined(ENABLE_OVERLOADING)
data TimerDestroyMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.OverloadedMethod TimerDestroyMethodInfo Timer signature where
    overloadedMethod = timerDestroy

instance O.OverloadedMethodInfo TimerDestroyMethodInfo Timer where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.Timer.timerDestroy",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-Timer.html#v:timerDestroy"
        })


#endif

-- method Timer::elapsed
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "timer"
--           , argType = TInterface Name { namespace = "GLib" , name = "Timer" }
--           , argCType = Just "GTimer*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GTimer." , sinceVersion = Nothing }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       , Arg
--           { argCName = "microseconds"
--           , argType = TBasicType TULong
--           , argCType = Just "gulong*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText =
--                     Just
--                       "return location for the fractional part of seconds\n               elapsed, in microseconds (that is, the total number\n               of microseconds elapsed, modulo 1000000), or %NULL"
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Just (TBasicType TDouble)
-- throws : False
-- Skip return : False

foreign import ccall "g_timer_elapsed" g_timer_elapsed :: 
    Ptr Timer ->                            -- timer : TInterface (Name {namespace = "GLib", name = "Timer"})
    FCT.CULong ->                           -- microseconds : TBasicType TULong
    IO CDouble

-- | If /@timer@/ has been started but not stopped, obtains the time since
-- the timer was started. If /@timer@/ has been stopped, obtains the
-- elapsed time between the time it was started and the time it was
-- stopped. The return value is the number of seconds elapsed,
-- including any fractional part. The /@microseconds@/ out parameter is
-- essentially useless.
timerElapsed ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Timer
    -- ^ /@timer@/: a t'GI.GLib.Structs.Timer.Timer'.
    -> FCT.CULong
    -- ^ /@microseconds@/: return location for the fractional part of seconds
    --                elapsed, in microseconds (that is, the total number
    --                of microseconds elapsed, modulo 1000000), or 'P.Nothing'
    -> m Double
    -- ^ __Returns:__ seconds elapsed as a floating point value, including any
    --          fractional part.
timerElapsed timer microseconds = liftIO $ do
    timer' <- unsafeManagedPtrGetPtr timer
    result <- g_timer_elapsed timer' microseconds
    let result' = realToFrac result
    touchManagedPtr timer
    return result'

#if defined(ENABLE_OVERLOADING)
data TimerElapsedMethodInfo
instance (signature ~ (FCT.CULong -> m Double), MonadIO m) => O.OverloadedMethod TimerElapsedMethodInfo Timer signature where
    overloadedMethod = timerElapsed

instance O.OverloadedMethodInfo TimerElapsedMethodInfo Timer where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.Timer.timerElapsed",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-Timer.html#v:timerElapsed"
        })


#endif

-- method Timer::is_active
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "timer"
--           , argType = TInterface Name { namespace = "GLib" , name = "Timer" }
--           , argCType = Just "GTimer*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GTimer." , sinceVersion = Nothing }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Just (TBasicType TBoolean)
-- throws : False
-- Skip return : False

foreign import ccall "g_timer_is_active" g_timer_is_active :: 
    Ptr Timer ->                            -- timer : TInterface (Name {namespace = "GLib", name = "Timer"})
    IO CInt

-- | Exposes whether the timer is currently active.
-- 
-- /Since: 2.62/
timerIsActive ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Timer
    -- ^ /@timer@/: a t'GI.GLib.Structs.Timer.Timer'.
    -> m Bool
    -- ^ __Returns:__ 'P.True' if the timer is running, 'P.False' otherwise
timerIsActive timer = liftIO $ do
    timer' <- unsafeManagedPtrGetPtr timer
    result <- g_timer_is_active timer'
    let result' = (/= 0) result
    touchManagedPtr timer
    return result'

#if defined(ENABLE_OVERLOADING)
data TimerIsActiveMethodInfo
instance (signature ~ (m Bool), MonadIO m) => O.OverloadedMethod TimerIsActiveMethodInfo Timer signature where
    overloadedMethod = timerIsActive

instance O.OverloadedMethodInfo TimerIsActiveMethodInfo Timer where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.Timer.timerIsActive",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-Timer.html#v:timerIsActive"
        })


#endif

-- method Timer::reset
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "timer"
--           , argType = TInterface Name { namespace = "GLib" , name = "Timer" }
--           , argCType = Just "GTimer*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GTimer." , sinceVersion = Nothing }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_timer_reset" g_timer_reset :: 
    Ptr Timer ->                            -- timer : TInterface (Name {namespace = "GLib", name = "Timer"})
    IO ()

-- | This function is useless; it\'s fine to call 'GI.GLib.Structs.Timer.timerStart' on an
-- already-started timer to reset the start time, so 'GI.GLib.Structs.Timer.timerReset'
-- serves no purpose.
timerReset ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Timer
    -- ^ /@timer@/: a t'GI.GLib.Structs.Timer.Timer'.
    -> m ()
timerReset timer = liftIO $ do
    timer' <- unsafeManagedPtrGetPtr timer
    g_timer_reset timer'
    touchManagedPtr timer
    return ()

#if defined(ENABLE_OVERLOADING)
data TimerResetMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.OverloadedMethod TimerResetMethodInfo Timer signature where
    overloadedMethod = timerReset

instance O.OverloadedMethodInfo TimerResetMethodInfo Timer where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.Timer.timerReset",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-Timer.html#v:timerReset"
        })


#endif

-- method Timer::start
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "timer"
--           , argType = TInterface Name { namespace = "GLib" , name = "Timer" }
--           , argCType = Just "GTimer*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GTimer." , sinceVersion = Nothing }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_timer_start" g_timer_start :: 
    Ptr Timer ->                            -- timer : TInterface (Name {namespace = "GLib", name = "Timer"})
    IO ()

-- | Marks a start time, so that future calls to 'GI.GLib.Structs.Timer.timerElapsed' will
-- report the time since 'GI.GLib.Structs.Timer.timerStart' was called. @/g_timer_new()/@
-- automatically marks the start time, so no need to call
-- 'GI.GLib.Structs.Timer.timerStart' immediately after creating the timer.
timerStart ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Timer
    -- ^ /@timer@/: a t'GI.GLib.Structs.Timer.Timer'.
    -> m ()
timerStart timer = liftIO $ do
    timer' <- unsafeManagedPtrGetPtr timer
    g_timer_start timer'
    touchManagedPtr timer
    return ()

#if defined(ENABLE_OVERLOADING)
data TimerStartMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.OverloadedMethod TimerStartMethodInfo Timer signature where
    overloadedMethod = timerStart

instance O.OverloadedMethodInfo TimerStartMethodInfo Timer where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.Timer.timerStart",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-Timer.html#v:timerStart"
        })


#endif

-- method Timer::stop
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "timer"
--           , argType = TInterface Name { namespace = "GLib" , name = "Timer" }
--           , argCType = Just "GTimer*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GTimer." , sinceVersion = Nothing }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_timer_stop" g_timer_stop :: 
    Ptr Timer ->                            -- timer : TInterface (Name {namespace = "GLib", name = "Timer"})
    IO ()

-- | Marks an end time, so calls to 'GI.GLib.Structs.Timer.timerElapsed' will return the
-- difference between this end time and the start time.
timerStop ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Timer
    -- ^ /@timer@/: a t'GI.GLib.Structs.Timer.Timer'.
    -> m ()
timerStop timer = liftIO $ do
    timer' <- unsafeManagedPtrGetPtr timer
    g_timer_stop timer'
    touchManagedPtr timer
    return ()

#if defined(ENABLE_OVERLOADING)
data TimerStopMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.OverloadedMethod TimerStopMethodInfo Timer signature where
    overloadedMethod = timerStop

instance O.OverloadedMethodInfo TimerStopMethodInfo Timer where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.GLib.Structs.Timer.timerStop",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-glib-2.0.30/docs/GI-GLib-Structs-Timer.html#v:timerStop"
        })


#endif

#if defined(ENABLE_OVERLOADING)
type family ResolveTimerMethod (t :: Symbol) (o :: DK.Type) :: DK.Type where
    ResolveTimerMethod "continue" o = TimerContinueMethodInfo
    ResolveTimerMethod "destroy" o = TimerDestroyMethodInfo
    ResolveTimerMethod "elapsed" o = TimerElapsedMethodInfo
    ResolveTimerMethod "isActive" o = TimerIsActiveMethodInfo
    ResolveTimerMethod "reset" o = TimerResetMethodInfo
    ResolveTimerMethod "start" o = TimerStartMethodInfo
    ResolveTimerMethod "stop" o = TimerStopMethodInfo
    ResolveTimerMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveTimerMethod t Timer, O.OverloadedMethod info Timer p) => OL.IsLabel t (Timer -> p) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.overloadedMethod @info
#else
    fromLabel _ = O.overloadedMethod @info
#endif

#if MIN_VERSION_base(4,13,0)
instance (info ~ ResolveTimerMethod t Timer, O.OverloadedMethod info Timer p, R.HasField t Timer p) => R.HasField t Timer p where
    getField = O.overloadedMethod @info

#endif

instance (info ~ ResolveTimerMethod t Timer, O.OverloadedMethodInfo info Timer) => OL.IsLabel t (O.MethodProxy info Timer) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.MethodProxy
#else
    fromLabel _ = O.MethodProxy
#endif

#endif


