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

    Structure representing a single field in a structured log entry. See
    @/g_log_structured()/@ for details.

    Log fields may contain arbitrary values, including binary with embedded nul
    bytes. If the field contains a string, the string must be UTF-8 encoded and
    have a trailing nul byte. Otherwise, /@length@/ must be set to a non-negative
    value.

    /Since: 2.50/
    -}

    #define ENABLE_OVERLOADING \
           (!defined(__HADDOCK_VERSION__))

    module GI.GLib.Structs.LogField
        (

    -- * Exported types
        LogField(..)                            ,
        newZeroLogField                         ,
        noLogField                              ,

     -- * Properties
    -- ** key #attr:key#
    {- | field name (UTF-8 string)
    -}
        clearLogFieldKey                        ,
        getLogFieldKey                          ,
    #if ENABLE_OVERLOADING
        logField_key                            ,
    #endif
        setLogFieldKey                          ,

    -- ** length #attr:length#
    {- | length of /@value@/, in bytes, or -1 if it is nul-terminated
    -}
        getLogFieldLength                       ,
    #if ENABLE_OVERLOADING
        logField_length                         ,
    #endif
        setLogFieldLength                       ,

    -- ** value #attr:value#
    {- | field value (arbitrary bytes)
    -}
        clearLogFieldValue                      ,
        getLogFieldValue                        ,
    #if ENABLE_OVERLOADING
        logField_value                          ,
    #endif
        setLogFieldValue                        ,

        ) 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

    -- | Memory-managed wrapper type.
    newtype LogField = LogField (ManagedPtr LogField)
    instance WrappedPtr LogField where
        wrappedPtrCalloc = callocBytes 24
        wrappedPtrCopy = \p -> withManagedPtr p (copyBytes 24 >=> wrapPtr LogField)
        wrappedPtrFree = Just ptr_to_g_free

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

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

    -- | A convenience alias for `Nothing` :: `Maybe` `LogField`.
    noLogField :: Maybe LogField
    noLogField = Nothing

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

    @
    'Data.GI.Base.Attributes.get' logField #key
    @
    -}
    getLogFieldKey :: MonadIO m => LogField -> m (Maybe T.Text)
    getLogFieldKey s = liftIO $ withManagedPtr s $ \ptr -> do
        val <- peek (ptr `plusPtr` 0) :: IO CString
        result <- SP.convertIfNonNull val $ \val' -> do
            val'' <- cstringToText val'
            return val''
        return result

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

    @
    'Data.GI.Base.Attributes.set' logField [ #key 'Data.GI.Base.Attributes.:=' value ]
    @
    -}
    setLogFieldKey :: MonadIO m => LogField -> CString -> m ()
    setLogFieldKey s val = liftIO $ withManagedPtr s $ \ptr -> do
        poke (ptr `plusPtr` 0) (val :: CString)

    {- |
    Set the value of the “@key@” field to `Nothing`.
    When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to

    @
    'Data.GI.Base.Attributes.clear' #key
    @
    -}
    clearLogFieldKey :: MonadIO m => LogField -> m ()
    clearLogFieldKey s = liftIO $ withManagedPtr s $ \ptr -> do
        poke (ptr `plusPtr` 0) (FP.nullPtr :: CString)

    #if ENABLE_OVERLOADING
    data LogFieldKeyFieldInfo
    instance AttrInfo LogFieldKeyFieldInfo where
        type AttrAllowedOps LogFieldKeyFieldInfo = '[ 'AttrSet, 'AttrGet, 'AttrClear]
        type AttrSetTypeConstraint LogFieldKeyFieldInfo = (~) CString
        type AttrBaseTypeConstraint LogFieldKeyFieldInfo = (~) LogField
        type AttrGetType LogFieldKeyFieldInfo = Maybe T.Text
        type AttrLabel LogFieldKeyFieldInfo = "key"
        type AttrOrigin LogFieldKeyFieldInfo = LogField
        attrGet _ = getLogFieldKey
        attrSet _ = setLogFieldKey
        attrConstruct = undefined
        attrClear _ = clearLogFieldKey

    logField_key :: AttrLabelProxy "key"
    logField_key = AttrLabelProxy

    #endif

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

    @
    'Data.GI.Base.Attributes.get' logField #value
    @
    -}
    getLogFieldValue :: MonadIO m => LogField -> m (Ptr ())
    getLogFieldValue s = liftIO $ withManagedPtr s $ \ptr -> do
        val <- peek (ptr `plusPtr` 8) :: IO (Ptr ())
        return val

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

    @
    'Data.GI.Base.Attributes.set' logField [ #value 'Data.GI.Base.Attributes.:=' value ]
    @
    -}
    setLogFieldValue :: MonadIO m => LogField -> Ptr () -> m ()
    setLogFieldValue s val = liftIO $ withManagedPtr s $ \ptr -> do
        poke (ptr `plusPtr` 8) (val :: Ptr ())

    {- |
    Set the value of the “@value@” field to `Nothing`.
    When <https://github.com/haskell-gi/haskell-gi/wiki/Overloading overloading> is enabled, this is equivalent to

    @
    'Data.GI.Base.Attributes.clear' #value
    @
    -}
    clearLogFieldValue :: MonadIO m => LogField -> m ()
    clearLogFieldValue s = liftIO $ withManagedPtr s $ \ptr -> do
        poke (ptr `plusPtr` 8) (FP.nullPtr :: Ptr ())

    #if ENABLE_OVERLOADING
    data LogFieldValueFieldInfo
    instance AttrInfo LogFieldValueFieldInfo where
        type AttrAllowedOps LogFieldValueFieldInfo = '[ 'AttrSet, 'AttrGet, 'AttrClear]
        type AttrSetTypeConstraint LogFieldValueFieldInfo = (~) (Ptr ())
        type AttrBaseTypeConstraint LogFieldValueFieldInfo = (~) LogField
        type AttrGetType LogFieldValueFieldInfo = Ptr ()
        type AttrLabel LogFieldValueFieldInfo = "value"
        type AttrOrigin LogFieldValueFieldInfo = LogField
        attrGet _ = getLogFieldValue
        attrSet _ = setLogFieldValue
        attrConstruct = undefined
        attrClear _ = clearLogFieldValue

    logField_value :: AttrLabelProxy "value"
    logField_value = AttrLabelProxy

    #endif

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

    @
    'Data.GI.Base.Attributes.get' logField #length
    @
    -}
    getLogFieldLength :: MonadIO m => LogField -> m Int64
    getLogFieldLength s = liftIO $ withManagedPtr s $ \ptr -> do
        val <- peek (ptr `plusPtr` 16) :: IO Int64
        return val

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

    @
    'Data.GI.Base.Attributes.set' logField [ #length 'Data.GI.Base.Attributes.:=' value ]
    @
    -}
    setLogFieldLength :: MonadIO m => LogField -> Int64 -> m ()
    setLogFieldLength s val = liftIO $ withManagedPtr s $ \ptr -> do
        poke (ptr `plusPtr` 16) (val :: Int64)

    #if ENABLE_OVERLOADING
    data LogFieldLengthFieldInfo
    instance AttrInfo LogFieldLengthFieldInfo where
        type AttrAllowedOps LogFieldLengthFieldInfo = '[ 'AttrSet, 'AttrGet]
        type AttrSetTypeConstraint LogFieldLengthFieldInfo = (~) Int64
        type AttrBaseTypeConstraint LogFieldLengthFieldInfo = (~) LogField
        type AttrGetType LogFieldLengthFieldInfo = Int64
        type AttrLabel LogFieldLengthFieldInfo = "length"
        type AttrOrigin LogFieldLengthFieldInfo = LogField
        attrGet _ = getLogFieldLength
        attrSet _ = setLogFieldLength
        attrConstruct = undefined
        attrClear _ = undefined

    logField_length :: AttrLabelProxy "length"
    logField_length = AttrLabelProxy

    #endif

    #if ENABLE_OVERLOADING
    instance O.HasAttributeList LogField
    type instance O.AttributeList LogField = LogFieldAttributeList
    type LogFieldAttributeList = ('[ '("key", LogFieldKeyFieldInfo), '("value", LogFieldValueFieldInfo), '("length", LogFieldLengthFieldInfo)] :: [(Symbol, *)])
    #endif

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

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

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