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

    'GI.Gio.Interfaces.Seekable.Seekable' is implemented by streams (implementations of
    'GI.Gio.Objects.InputStream.InputStream' or 'GI.Gio.Objects.OutputStream.OutputStream') that support seeking.

    Seekable streams largely fall into two categories: resizable and
    fixed-size.

    'GI.Gio.Interfaces.Seekable.Seekable' on fixed-sized streams is approximately the same as POSIX
    @/lseek()/@ on a block device (for example: attempting to seek past the
    end of the device is an error).  Fixed streams typically cannot be
    truncated.

    'GI.Gio.Interfaces.Seekable.Seekable' on resizable streams is approximately the same as POSIX
    @/lseek()/@ on a normal file.  Seeking past the end and writing data will
    usually cause the stream to resize by introducing zero bytes.
    -}

    #define ENABLE_OVERLOADING \
           (!defined(__HADDOCK_VERSION__))

    module GI.Gio.Interfaces.Seekable
        (

    -- * Exported types
        Seekable(..)                            ,
        noSeekable                              ,
        IsSeekable                              ,
        toSeekable                              ,

     -- * Methods
    -- ** canSeek #method:canSeek#

    #if ENABLE_OVERLOADING
        SeekableCanSeekMethodInfo               ,
    #endif
        seekableCanSeek                         ,

    -- ** canTruncate #method:canTruncate#

    #if ENABLE_OVERLOADING
        SeekableCanTruncateMethodInfo           ,
    #endif
        seekableCanTruncate                     ,

    -- ** seek #method:seek#

    #if ENABLE_OVERLOADING
        SeekableSeekMethodInfo                  ,
    #endif
        seekableSeek                            ,

    -- ** tell #method:tell#

    #if ENABLE_OVERLOADING
        SeekableTellMethodInfo                  ,
    #endif
        seekableTell                            ,

    -- ** truncate #method:truncate#

    #if ENABLE_OVERLOADING
        SeekableTruncateMethodInfo              ,
    #endif
        seekableTruncate                        ,

        ) 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.GLib.Enums as GLib.Enums
    import qualified GI.GObject.Objects.Object as GObject.Object
    import {-# SOURCE #-} qualified GI.Gio.Objects.Cancellable as Gio.Cancellable

    -- interface Seekable
    -- | Memory-managed wrapper type.
    newtype Seekable = Seekable (ManagedPtr Seekable)
    -- | A convenience alias for `Nothing` :: `Maybe` `Seekable`.
    noSeekable :: Maybe Seekable
    noSeekable = Nothing

    #if ENABLE_OVERLOADING
    type instance O.SignalList Seekable = SeekableSignalList
    type SeekableSignalList = ('[ '("notify", GObject.Object.ObjectNotifySignalInfo)] :: [(Symbol, *)])

    #endif

    foreign import ccall "g_seekable_get_type"
        c_g_seekable_get_type :: IO GType

    instance GObject Seekable where
        gobjectType _ = c_g_seekable_get_type

    -- | Type class for types which can be safely cast to `Seekable`, for instance with `toSeekable`.
    class GObject o => IsSeekable o
    #if MIN_VERSION_base(4,9,0)
    instance {-# OVERLAPPABLE #-} (GObject a, O.UnknownAncestorError Seekable a) =>
        IsSeekable a
    #endif
    instance IsSeekable Seekable
    instance GObject.Object.IsObject Seekable

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

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

    #if ENABLE_OVERLOADING
    #endif

    #if ENABLE_OVERLOADING
    type family ResolveSeekableMethod (t :: Symbol) (o :: *) :: * where
        ResolveSeekableMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
        ResolveSeekableMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
        ResolveSeekableMethod "canSeek" o = SeekableCanSeekMethodInfo
        ResolveSeekableMethod "canTruncate" o = SeekableCanTruncateMethodInfo
        ResolveSeekableMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
        ResolveSeekableMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
        ResolveSeekableMethod "getv" o = GObject.Object.ObjectGetvMethodInfo
        ResolveSeekableMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
        ResolveSeekableMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
        ResolveSeekableMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
        ResolveSeekableMethod "ref" o = GObject.Object.ObjectRefMethodInfo
        ResolveSeekableMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
        ResolveSeekableMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
        ResolveSeekableMethod "seek" o = SeekableSeekMethodInfo
        ResolveSeekableMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
        ResolveSeekableMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
        ResolveSeekableMethod "tell" o = SeekableTellMethodInfo
        ResolveSeekableMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
        ResolveSeekableMethod "truncate" o = SeekableTruncateMethodInfo
        ResolveSeekableMethod "unref" o = GObject.Object.ObjectUnrefMethodInfo
        ResolveSeekableMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
        ResolveSeekableMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
        ResolveSeekableMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
        ResolveSeekableMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
        ResolveSeekableMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
        ResolveSeekableMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
        ResolveSeekableMethod l o = O.MethodResolutionFailed l o

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

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

    -- method Seekable::can_seek
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "seekable", argType = TInterface (Name {namespace = "Gio", name = "Seekable"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GSeekable.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TBasicType TBoolean)
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_seekable_can_seek" g_seekable_can_seek ::
        Ptr Seekable ->                         -- seekable : TInterface (Name {namespace = "Gio", name = "Seekable"})
        IO CInt

    {- |
    Tests if the stream supports the 'GI.Gio.Structs.SeekableIface.SeekableIface'.
    -}
    seekableCanSeek ::
        (B.CallStack.HasCallStack, MonadIO m, IsSeekable a) =>
        a
        {- ^ /@seekable@/: a 'GI.Gio.Interfaces.Seekable.Seekable'. -}
        -> m Bool
        {- ^ __Returns:__ 'True' if /@seekable@/ can be seeked. 'False' otherwise. -}
    seekableCanSeek seekable = liftIO $ do
        seekable' <- unsafeManagedPtrCastPtr seekable
        result <- g_seekable_can_seek seekable'
        let result' = (/= 0) result
        touchManagedPtr seekable
        return result'

    #if ENABLE_OVERLOADING
    data SeekableCanSeekMethodInfo
    instance (signature ~ (m Bool), MonadIO m, IsSeekable a) => O.MethodInfo SeekableCanSeekMethodInfo a signature where
        overloadedMethod _ = seekableCanSeek

    #endif

    -- method Seekable::can_truncate
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "seekable", argType = TInterface (Name {namespace = "Gio", name = "Seekable"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GSeekable.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TBasicType TBoolean)
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_seekable_can_truncate" g_seekable_can_truncate ::
        Ptr Seekable ->                         -- seekable : TInterface (Name {namespace = "Gio", name = "Seekable"})
        IO CInt

    {- |
    Tests if the length of the stream can be adjusted with
    'GI.Gio.Interfaces.Seekable.seekableTruncate'.
    -}
    seekableCanTruncate ::
        (B.CallStack.HasCallStack, MonadIO m, IsSeekable a) =>
        a
        {- ^ /@seekable@/: a 'GI.Gio.Interfaces.Seekable.Seekable'. -}
        -> m Bool
        {- ^ __Returns:__ 'True' if the stream can be truncated, 'False' otherwise. -}
    seekableCanTruncate seekable = liftIO $ do
        seekable' <- unsafeManagedPtrCastPtr seekable
        result <- g_seekable_can_truncate seekable'
        let result' = (/= 0) result
        touchManagedPtr seekable
        return result'

    #if ENABLE_OVERLOADING
    data SeekableCanTruncateMethodInfo
    instance (signature ~ (m Bool), MonadIO m, IsSeekable a) => O.MethodInfo SeekableCanTruncateMethodInfo a signature where
        overloadedMethod _ = seekableCanTruncate

    #endif

    -- method Seekable::seek
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "seekable", argType = TInterface (Name {namespace = "Gio", name = "Seekable"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GSeekable.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "offset", argType = TBasicType TInt64, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #goffset.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "type", argType = TInterface (Name {namespace = "GLib", name = "SeekType"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GSeekType.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "cancellable", argType = TInterface (Name {namespace = "Gio", name = "Cancellable"}), direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "optional #GCancellable object, %NULL to ignore.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TBasicType TBoolean)
    -- throws : True
    -- Skip return : False

    foreign import ccall "g_seekable_seek" g_seekable_seek ::
        Ptr Seekable ->                         -- seekable : TInterface (Name {namespace = "Gio", name = "Seekable"})
        Int64 ->                                -- offset : TBasicType TInt64
        CUInt ->                                -- type : TInterface (Name {namespace = "GLib", name = "SeekType"})
        Ptr Gio.Cancellable.Cancellable ->      -- cancellable : TInterface (Name {namespace = "Gio", name = "Cancellable"})
        Ptr (Ptr GError) ->                     -- error
        IO CInt

    {- |
    Seeks in the stream by the given /@offset@/, modified by /@type@/.

    Attempting to seek past the end of the stream will have different
    results depending on if the stream is fixed-sized or resizable.  If
    the stream is resizable then seeking past the end and then writing
    will result in zeros filling the empty space.  Seeking past the end
    of a resizable stream and reading will result in EOF.  Seeking past
    the end of a fixed-sized stream will fail.

    Any operation that would result in a negative offset will fail.

    If /@cancellable@/ is not 'Nothing', then the operation can be cancelled by
    triggering the cancellable object from another thread. If the operation
    was cancelled, the error 'GI.Gio.Enums.IOErrorEnumCancelled' will be returned.
    -}
    seekableSeek ::
        (B.CallStack.HasCallStack, MonadIO m, IsSeekable a, Gio.Cancellable.IsCancellable b) =>
        a
        {- ^ /@seekable@/: a 'GI.Gio.Interfaces.Seekable.Seekable'. -}
        -> Int64
        {- ^ /@offset@/: a @/goffset/@. -}
        -> GLib.Enums.SeekType
        {- ^ /@type@/: a 'GI.GLib.Enums.SeekType'. -}
        -> Maybe (b)
        {- ^ /@cancellable@/: optional 'GI.Gio.Objects.Cancellable.Cancellable' object, 'Nothing' to ignore. -}
        -> m ()
        {- ^ /(Can throw 'Data.GI.Base.GError.GError')/ -}
    seekableSeek seekable offset type_ cancellable = liftIO $ do
        seekable' <- unsafeManagedPtrCastPtr seekable
        let type_' = (fromIntegral . fromEnum) type_
        maybeCancellable <- case cancellable of
            Nothing -> return nullPtr
            Just jCancellable -> do
                jCancellable' <- unsafeManagedPtrCastPtr jCancellable
                return jCancellable'
        onException (do
            _ <- propagateGError $ g_seekable_seek seekable' offset type_' maybeCancellable
            touchManagedPtr seekable
            whenJust cancellable touchManagedPtr
            return ()
         ) (do
            return ()
         )

    #if ENABLE_OVERLOADING
    data SeekableSeekMethodInfo
    instance (signature ~ (Int64 -> GLib.Enums.SeekType -> Maybe (b) -> m ()), MonadIO m, IsSeekable a, Gio.Cancellable.IsCancellable b) => O.MethodInfo SeekableSeekMethodInfo a signature where
        overloadedMethod _ = seekableSeek

    #endif

    -- method Seekable::tell
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "seekable", argType = TInterface (Name {namespace = "Gio", name = "Seekable"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GSeekable.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TBasicType TInt64)
    -- throws : False
    -- Skip return : False

    foreign import ccall "g_seekable_tell" g_seekable_tell ::
        Ptr Seekable ->                         -- seekable : TInterface (Name {namespace = "Gio", name = "Seekable"})
        IO Int64

    {- |
    Tells the current position within the stream.
    -}
    seekableTell ::
        (B.CallStack.HasCallStack, MonadIO m, IsSeekable a) =>
        a
        {- ^ /@seekable@/: a 'GI.Gio.Interfaces.Seekable.Seekable'. -}
        -> m Int64
        {- ^ __Returns:__ the offset from the beginning of the buffer. -}
    seekableTell seekable = liftIO $ do
        seekable' <- unsafeManagedPtrCastPtr seekable
        result <- g_seekable_tell seekable'
        touchManagedPtr seekable
        return result

    #if ENABLE_OVERLOADING
    data SeekableTellMethodInfo
    instance (signature ~ (m Int64), MonadIO m, IsSeekable a) => O.MethodInfo SeekableTellMethodInfo a signature where
        overloadedMethod _ = seekableTell

    #endif

    -- method Seekable::truncate
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "seekable", argType = TInterface (Name {namespace = "Gio", name = "Seekable"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GSeekable.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "offset", argType = TBasicType TInt64, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "new length for @seekable, in bytes.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "cancellable", argType = TInterface (Name {namespace = "Gio", name = "Cancellable"}), direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "optional #GCancellable object, %NULL to ignore.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TBasicType TBoolean)
    -- throws : True
    -- Skip return : False

    foreign import ccall "g_seekable_truncate" g_seekable_truncate ::
        Ptr Seekable ->                         -- seekable : TInterface (Name {namespace = "Gio", name = "Seekable"})
        Int64 ->                                -- offset : TBasicType TInt64
        Ptr Gio.Cancellable.Cancellable ->      -- cancellable : TInterface (Name {namespace = "Gio", name = "Cancellable"})
        Ptr (Ptr GError) ->                     -- error
        IO CInt

    {- |
    Sets the length of the stream to /@offset@/. If the stream was previously
    larger than /@offset@/, the extra data is discarded. If the stream was
    previouly shorter than /@offset@/, it is extended with NUL (\'\\0\') bytes.

    If /@cancellable@/ is not 'Nothing', then the operation can be cancelled by
    triggering the cancellable object from another thread. If the operation
    was cancelled, the error 'GI.Gio.Enums.IOErrorEnumCancelled' will be returned. If an
    operation was partially finished when the operation was cancelled the
    partial result will be returned, without an error.
    -}
    seekableTruncate ::
        (B.CallStack.HasCallStack, MonadIO m, IsSeekable a, Gio.Cancellable.IsCancellable b) =>
        a
        {- ^ /@seekable@/: a 'GI.Gio.Interfaces.Seekable.Seekable'. -}
        -> Int64
        {- ^ /@offset@/: new length for /@seekable@/, in bytes. -}
        -> Maybe (b)
        {- ^ /@cancellable@/: optional 'GI.Gio.Objects.Cancellable.Cancellable' object, 'Nothing' to ignore. -}
        -> m ()
        {- ^ /(Can throw 'Data.GI.Base.GError.GError')/ -}
    seekableTruncate seekable offset cancellable = liftIO $ do
        seekable' <- unsafeManagedPtrCastPtr seekable
        maybeCancellable <- case cancellable of
            Nothing -> return nullPtr
            Just jCancellable -> do
                jCancellable' <- unsafeManagedPtrCastPtr jCancellable
                return jCancellable'
        onException (do
            _ <- propagateGError $ g_seekable_truncate seekable' offset maybeCancellable
            touchManagedPtr seekable
            whenJust cancellable touchManagedPtr
            return ()
         ) (do
            return ()
         )

    #if ENABLE_OVERLOADING
    data SeekableTruncateMethodInfo
    instance (signature ~ (Int64 -> Maybe (b) -> m ()), MonadIO m, IsSeekable a, Gio.Cancellable.IsCancellable b) => O.MethodInfo SeekableTruncateMethodInfo a signature where
        overloadedMethod _ = seekableTruncate

    #endif