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

    A 'GI.Gio.Objects.ThreadedSocketService.ThreadedSocketService' is a simple subclass of 'GI.Gio.Objects.SocketService.SocketService'
    that handles incoming connections by creating a worker thread and
    dispatching the connection to it by emitting the
    'GI.Gio.Objects.ThreadedSocketService.ThreadedSocketService'::@/run/@ signal in the new thread.

    The signal handler may perform blocking IO and need not return
    until the connection is closed.

    The service is implemented using a thread pool, so there is a
    limited amount of threads available to serve incoming requests.
    The service automatically stops the 'GI.Gio.Objects.SocketService.SocketService' from accepting
    new connections when all threads are busy.

    As with 'GI.Gio.Objects.SocketService.SocketService', you may connect to 'GI.Gio.Objects.ThreadedSocketService.ThreadedSocketService'::@/run/@,
    or subclass and override the default handler.

    /Since: 2.22/
    -}

    #define ENABLE_OVERLOADING \
           (!defined(__HADDOCK_VERSION__))

    module GI.Gio.Objects.ThreadedSocketService
        (

    -- * Exported types
        ThreadedSocketService(..)               ,
        IsThreadedSocketService                 ,
        toThreadedSocketService                 ,
        noThreadedSocketService                 ,

     -- * Methods
    -- ** new #method:new#

        threadedSocketServiceNew                ,

     -- * Properties
    -- ** maxThreads #attr:maxThreads#
    {- | /No description available in the introspection data./
    -}
    #if ENABLE_OVERLOADING
        ThreadedSocketServiceMaxThreadsPropertyInfo,
    #endif
        constructThreadedSocketServiceMaxThreads,
        getThreadedSocketServiceMaxThreads      ,
    #if ENABLE_OVERLOADING
        threadedSocketServiceMaxThreads         ,
    #endif

     -- * Signals
    -- ** run #signal:run#

        C_ThreadedSocketServiceRunCallback      ,
        ThreadedSocketServiceRunCallback        ,
    #if ENABLE_OVERLOADING
        ThreadedSocketServiceRunSignalInfo      ,
    #endif
        afterThreadedSocketServiceRun           ,
        genClosure_ThreadedSocketServiceRun     ,
        mk_ThreadedSocketServiceRunCallback     ,
        noThreadedSocketServiceRunCallback      ,
        onThreadedSocketServiceRun              ,
        wrap_ThreadedSocketServiceRunCallback   ,

        ) 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.Objects.SocketConnection as Gio.SocketConnection
    import {-# SOURCE #-} qualified GI.Gio.Objects.SocketListener as Gio.SocketListener
    import {-# SOURCE #-} qualified GI.Gio.Objects.SocketService as Gio.SocketService

    -- | Memory-managed wrapper type.
    newtype ThreadedSocketService = ThreadedSocketService (ManagedPtr ThreadedSocketService)
    foreign import ccall "g_threaded_socket_service_get_type"
        c_g_threaded_socket_service_get_type :: IO GType

    instance GObject ThreadedSocketService where
        gobjectType _ = c_g_threaded_socket_service_get_type

    -- | Type class for types which can be safely cast to `ThreadedSocketService`, for instance with `toThreadedSocketService`.
    class GObject o => IsThreadedSocketService o
    #if MIN_VERSION_base(4,9,0)
    instance {-# OVERLAPPABLE #-} (GObject a, O.UnknownAncestorError ThreadedSocketService a) =>
        IsThreadedSocketService a
    #endif
    instance IsThreadedSocketService ThreadedSocketService
    instance Gio.SocketService.IsSocketService ThreadedSocketService
    instance Gio.SocketListener.IsSocketListener ThreadedSocketService
    instance GObject.Object.IsObject ThreadedSocketService

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

    -- | A convenience alias for `Nothing` :: `Maybe` `ThreadedSocketService`.
    noThreadedSocketService :: Maybe ThreadedSocketService
    noThreadedSocketService = Nothing

    #if ENABLE_OVERLOADING
    type family ResolveThreadedSocketServiceMethod (t :: Symbol) (o :: *) :: * where
        ResolveThreadedSocketServiceMethod "accept" o = Gio.SocketListener.SocketListenerAcceptMethodInfo
        ResolveThreadedSocketServiceMethod "acceptAsync" o = Gio.SocketListener.SocketListenerAcceptAsyncMethodInfo
        ResolveThreadedSocketServiceMethod "acceptFinish" o = Gio.SocketListener.SocketListenerAcceptFinishMethodInfo
        ResolveThreadedSocketServiceMethod "acceptSocket" o = Gio.SocketListener.SocketListenerAcceptSocketMethodInfo
        ResolveThreadedSocketServiceMethod "acceptSocketAsync" o = Gio.SocketListener.SocketListenerAcceptSocketAsyncMethodInfo
        ResolveThreadedSocketServiceMethod "acceptSocketFinish" o = Gio.SocketListener.SocketListenerAcceptSocketFinishMethodInfo
        ResolveThreadedSocketServiceMethod "addAddress" o = Gio.SocketListener.SocketListenerAddAddressMethodInfo
        ResolveThreadedSocketServiceMethod "addAnyInetPort" o = Gio.SocketListener.SocketListenerAddAnyInetPortMethodInfo
        ResolveThreadedSocketServiceMethod "addInetPort" o = Gio.SocketListener.SocketListenerAddInetPortMethodInfo
        ResolveThreadedSocketServiceMethod "addSocket" o = Gio.SocketListener.SocketListenerAddSocketMethodInfo
        ResolveThreadedSocketServiceMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
        ResolveThreadedSocketServiceMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
        ResolveThreadedSocketServiceMethod "close" o = Gio.SocketListener.SocketListenerCloseMethodInfo
        ResolveThreadedSocketServiceMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
        ResolveThreadedSocketServiceMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
        ResolveThreadedSocketServiceMethod "getv" o = GObject.Object.ObjectGetvMethodInfo
        ResolveThreadedSocketServiceMethod "isActive" o = Gio.SocketService.SocketServiceIsActiveMethodInfo
        ResolveThreadedSocketServiceMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
        ResolveThreadedSocketServiceMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
        ResolveThreadedSocketServiceMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
        ResolveThreadedSocketServiceMethod "ref" o = GObject.Object.ObjectRefMethodInfo
        ResolveThreadedSocketServiceMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
        ResolveThreadedSocketServiceMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
        ResolveThreadedSocketServiceMethod "start" o = Gio.SocketService.SocketServiceStartMethodInfo
        ResolveThreadedSocketServiceMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
        ResolveThreadedSocketServiceMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
        ResolveThreadedSocketServiceMethod "stop" o = Gio.SocketService.SocketServiceStopMethodInfo
        ResolveThreadedSocketServiceMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
        ResolveThreadedSocketServiceMethod "unref" o = GObject.Object.ObjectUnrefMethodInfo
        ResolveThreadedSocketServiceMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
        ResolveThreadedSocketServiceMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
        ResolveThreadedSocketServiceMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
        ResolveThreadedSocketServiceMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
        ResolveThreadedSocketServiceMethod "setBacklog" o = Gio.SocketListener.SocketListenerSetBacklogMethodInfo
        ResolveThreadedSocketServiceMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
        ResolveThreadedSocketServiceMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
        ResolveThreadedSocketServiceMethod l o = O.MethodResolutionFailed l o

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

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

    -- signal ThreadedSocketService::run
    {- |
    The ::run signal is emitted in a worker thread in response to an
    incoming connection. This thread is dedicated to handling
    /@connection@/ and may perform blocking IO. The signal handler need
    not return until the connection is closed.
    -}
    type ThreadedSocketServiceRunCallback =
        Gio.SocketConnection.SocketConnection
        {- ^ /@connection@/: a new 'GI.Gio.Objects.SocketConnection.SocketConnection' object. -}
        -> GObject.Object.Object
        {- ^ /@sourceObject@/: the source_object passed to 'GI.Gio.Objects.SocketListener.socketListenerAddAddress'. -}
        -> IO Bool
        {- ^ __Returns:__ 'True' to stop further signal handlers from being called -}

    -- | A convenience synonym for @`Nothing` :: `Maybe` `ThreadedSocketServiceRunCallback`@.
    noThreadedSocketServiceRunCallback :: Maybe ThreadedSocketServiceRunCallback
    noThreadedSocketServiceRunCallback = Nothing

    -- | Type for the callback on the (unwrapped) C side.
    type C_ThreadedSocketServiceRunCallback =
        Ptr () ->                               -- object
        Ptr Gio.SocketConnection.SocketConnection ->
        Ptr GObject.Object.Object ->
        Ptr () ->                               -- user_data
        IO CInt

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

    -- | Wrap the callback into a `Closure`.
    genClosure_ThreadedSocketServiceRun :: ThreadedSocketServiceRunCallback -> IO Closure
    genClosure_ThreadedSocketServiceRun cb = do
        let cb' = wrap_ThreadedSocketServiceRunCallback cb
        mk_ThreadedSocketServiceRunCallback cb' >>= newCClosure

    -- | Wrap a `ThreadedSocketServiceRunCallback` into a `C_ThreadedSocketServiceRunCallback`.
    wrap_ThreadedSocketServiceRunCallback ::
        ThreadedSocketServiceRunCallback ->
        C_ThreadedSocketServiceRunCallback
    wrap_ThreadedSocketServiceRunCallback _cb _ connection sourceObject _ = do
        connection' <- (newObject Gio.SocketConnection.SocketConnection) connection
        sourceObject' <- (newObject GObject.Object.Object) sourceObject
        result <- _cb  connection' sourceObject'
        let result' = (fromIntegral . fromEnum) result
        return result'

    {- |
    Connect a signal handler for the “@run@” 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' threadedSocketService #run callback
    @
    -}
    onThreadedSocketServiceRun :: (IsThreadedSocketService a, MonadIO m) => a -> ThreadedSocketServiceRunCallback -> m SignalHandlerId
    onThreadedSocketServiceRun obj cb = liftIO $ do
        let cb' = wrap_ThreadedSocketServiceRunCallback cb
        cb'' <- mk_ThreadedSocketServiceRunCallback cb'
        connectSignalFunPtr obj "run" cb'' SignalConnectBefore

    {- |
    Connect a signal handler for the “@run@” 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' threadedSocketService #run callback
    @
    -}
    afterThreadedSocketServiceRun :: (IsThreadedSocketService a, MonadIO m) => a -> ThreadedSocketServiceRunCallback -> m SignalHandlerId
    afterThreadedSocketServiceRun obj cb = liftIO $ do
        let cb' = wrap_ThreadedSocketServiceRunCallback cb
        cb'' <- mk_ThreadedSocketServiceRunCallback cb'
        connectSignalFunPtr obj "run" cb'' SignalConnectAfter

    -- VVV Prop "max-threads"
       -- Type: TBasicType TInt
       -- Flags: [PropertyReadable,PropertyWritable,PropertyConstructOnly]
       -- Nullable: (Nothing,Nothing)

    {- |
    Get the value of the “@max-threads@” property.
    When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to

    @
    'Data.GI.Base.Attributes.get' threadedSocketService #maxThreads
    @
    -}
    getThreadedSocketServiceMaxThreads :: (MonadIO m, IsThreadedSocketService o) => o -> m Int32
    getThreadedSocketServiceMaxThreads obj = liftIO $ getObjectPropertyInt32 obj "max-threads"

    {- |
    Construct a `GValueConstruct` with valid value for the “@max-threads@” property. This is rarely needed directly, but it is used by `Data.GI.Base.Constructible.new`.
    -}
    constructThreadedSocketServiceMaxThreads :: (IsThreadedSocketService o) => Int32 -> IO (GValueConstruct o)
    constructThreadedSocketServiceMaxThreads val = constructObjectPropertyInt32 "max-threads" val

    #if ENABLE_OVERLOADING
    data ThreadedSocketServiceMaxThreadsPropertyInfo
    instance AttrInfo ThreadedSocketServiceMaxThreadsPropertyInfo where
        type AttrAllowedOps ThreadedSocketServiceMaxThreadsPropertyInfo = '[ 'AttrConstruct, 'AttrGet]
        type AttrSetTypeConstraint ThreadedSocketServiceMaxThreadsPropertyInfo = (~) Int32
        type AttrBaseTypeConstraint ThreadedSocketServiceMaxThreadsPropertyInfo = IsThreadedSocketService
        type AttrGetType ThreadedSocketServiceMaxThreadsPropertyInfo = Int32
        type AttrLabel ThreadedSocketServiceMaxThreadsPropertyInfo = "max-threads"
        type AttrOrigin ThreadedSocketServiceMaxThreadsPropertyInfo = ThreadedSocketService
        attrGet _ = getThreadedSocketServiceMaxThreads
        attrSet _ = undefined
        attrConstruct _ = constructThreadedSocketServiceMaxThreads
        attrClear _ = undefined
    #endif

    #if ENABLE_OVERLOADING
    instance O.HasAttributeList ThreadedSocketService
    type instance O.AttributeList ThreadedSocketService = ThreadedSocketServiceAttributeList
    type ThreadedSocketServiceAttributeList = ('[ '("active", Gio.SocketService.SocketServiceActivePropertyInfo), '("listenBacklog", Gio.SocketListener.SocketListenerListenBacklogPropertyInfo), '("maxThreads", ThreadedSocketServiceMaxThreadsPropertyInfo)] :: [(Symbol, *)])
    #endif

    #if ENABLE_OVERLOADING
    threadedSocketServiceMaxThreads :: AttrLabelProxy "maxThreads"
    threadedSocketServiceMaxThreads = AttrLabelProxy

    #endif

    #if ENABLE_OVERLOADING
    data ThreadedSocketServiceRunSignalInfo
    instance SignalInfo ThreadedSocketServiceRunSignalInfo where
        type HaskellCallbackType ThreadedSocketServiceRunSignalInfo = ThreadedSocketServiceRunCallback
        connectSignal _ obj cb connectMode = do
            let cb' = wrap_ThreadedSocketServiceRunCallback cb
            cb'' <- mk_ThreadedSocketServiceRunCallback cb'
            connectSignalFunPtr obj "run" cb'' connectMode

    type instance O.SignalList ThreadedSocketService = ThreadedSocketServiceSignalList
    type ThreadedSocketServiceSignalList = ('[ '("event", Gio.SocketListener.SocketListenerEventSignalInfo), '("incoming", Gio.SocketService.SocketServiceIncomingSignalInfo), '("notify", GObject.Object.ObjectNotifySignalInfo), '("run", ThreadedSocketServiceRunSignalInfo)] :: [(Symbol, *)])

    #endif

    -- method ThreadedSocketService::new
    -- method type : Constructor
    -- Args : [Arg {argCName = "max_threads", argType = TBasicType TInt, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the maximal number of threads to execute concurrently\n  handling incoming clients, -1 means no limit", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TInterface (Name {namespace = "Gio", name = "ThreadedSocketService"}))
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_threaded_socket_service_new" g_threaded_socket_service_new ::
        Int32 ->                                -- max_threads : TBasicType TInt
        IO (Ptr ThreadedSocketService)

    {- |
    Creates a new 'GI.Gio.Objects.ThreadedSocketService.ThreadedSocketService' with no listeners. Listeners
    must be added with one of the 'GI.Gio.Objects.SocketListener.SocketListener' \"add\" methods.

    /Since: 2.22/
    -}
    threadedSocketServiceNew ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        Int32
        {- ^ /@maxThreads@/: the maximal number of threads to execute concurrently
      handling incoming clients, -1 means no limit -}
        -> m ThreadedSocketService
        {- ^ __Returns:__ a new 'GI.Gio.Objects.SocketService.SocketService'. -}
    threadedSocketServiceNew maxThreads = liftIO $ do
        result <- g_threaded_socket_service_new maxThreads
        checkUnexpectedReturnNULL "threadedSocketServiceNew" result
        result' <- (wrapObject ThreadedSocketService) result
        return result'

    #if ENABLE_OVERLOADING
    #endif