    {- |
    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 'GI.Pango.Structs.AttrIterator.AttrIterator' structure is used to represent an
    iterator through a 'GI.Pango.Structs.AttrList.AttrList'. A new iterator is created
    with @/pango_attr_list_get_iterator()/@. Once the iterator
    is created, it can be advanced through the style changes
    in the text using 'GI.Pango.Structs.AttrIterator.attrIteratorNext'. At each
    style change, the range of the current style segment and the
    attributes currently in effect can be queried.
    -}

    #define ENABLE_OVERLOADING \
           (!defined(__HADDOCK_VERSION__))

    module GI.Pango.Structs.AttrIterator
        (

    -- * Exported types
        AttrIterator(..)                        ,
        noAttrIterator                          ,

     -- * Methods
    -- ** destroy #method:destroy#

    #if ENABLE_OVERLOADING
        AttrIteratorDestroyMethodInfo           ,
    #endif
        attrIteratorDestroy                     ,

    -- ** getAttrs #method:getAttrs#

    #if ENABLE_OVERLOADING
        AttrIteratorGetAttrsMethodInfo          ,
    #endif
        attrIteratorGetAttrs                    ,

    -- ** getFont #method:getFont#

    #if ENABLE_OVERLOADING
        AttrIteratorGetFontMethodInfo           ,
    #endif
        attrIteratorGetFont                     ,

    -- ** next #method:next#

    #if ENABLE_OVERLOADING
        AttrIteratorNextMethodInfo              ,
    #endif
        attrIteratorNext                        ,

    -- ** range #method:range#

    #if ENABLE_OVERLOADING
        AttrIteratorRangeMethodInfo             ,
    #endif
        attrIteratorRange                       ,

        ) 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 {-# SOURCE #-} qualified GI.Pango.Structs.Attribute as Pango.Attribute
    import {-# SOURCE #-} qualified GI.Pango.Structs.FontDescription as Pango.FontDescription
    import {-# SOURCE #-} qualified GI.Pango.Structs.Language as Pango.Language

    -- | Memory-managed wrapper type.
    newtype AttrIterator = AttrIterator (ManagedPtr AttrIterator)
    -- XXX Wrapping a foreign struct/union with no known destructor or size, leak?
    instance WrappedPtr AttrIterator where
        wrappedPtrCalloc = return nullPtr
        wrappedPtrCopy = return
        wrappedPtrFree = Nothing

    -- | A convenience alias for `Nothing` :: `Maybe` `AttrIterator`.
    noAttrIterator :: Maybe AttrIterator
    noAttrIterator = Nothing

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

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

    foreign import ccall "pango_attr_iterator_destroy" pango_attr_iterator_destroy ::
        Ptr AttrIterator ->                     -- iterator : TInterface (Name {namespace = "Pango", name = "AttrIterator"})
        IO ()

    {- |
    Destroy a 'GI.Pango.Structs.AttrIterator.AttrIterator' and free all associated memory.
    -}
    attrIteratorDestroy ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        AttrIterator
        {- ^ /@iterator@/: a 'GI.Pango.Structs.AttrIterator.AttrIterator'. -}
        -> m ()
    attrIteratorDestroy iterator = liftIO $ do
        iterator' <- unsafeManagedPtrGetPtr iterator
        pango_attr_iterator_destroy iterator'
        touchManagedPtr iterator
        return ()

    #if ENABLE_OVERLOADING
    data AttrIteratorDestroyMethodInfo
    instance (signature ~ (m ()), MonadIO m) => O.MethodInfo AttrIteratorDestroyMethodInfo AttrIterator signature where
        overloadedMethod _ = attrIteratorDestroy

    #endif

    -- method AttrIterator::get_attrs
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "iterator", argType = TInterface (Name {namespace = "Pango", name = "AttrIterator"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #PangoAttrIterator", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
    -- Lengths : []
    -- returnType : Just (TGSList (TInterface (Name {namespace = "Pango", name = "Attribute"})))
    -- throws : False
    -- Skip return : False

    foreign import ccall "pango_attr_iterator_get_attrs" pango_attr_iterator_get_attrs ::
        Ptr AttrIterator ->                     -- iterator : TInterface (Name {namespace = "Pango", name = "AttrIterator"})
        IO (Ptr (GSList (Ptr Pango.Attribute.Attribute)))

    {- |
    Gets a list of all attributes at the current position of the
    iterator.

    /Since: 1.2/
    -}
    attrIteratorGetAttrs ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        AttrIterator
        {- ^ /@iterator@/: a 'GI.Pango.Structs.AttrIterator.AttrIterator' -}
        -> m [Pango.Attribute.Attribute]
        {- ^ __Returns:__ a list of
      all attributes for the current range.
      To free this value, call 'GI.Pango.Structs.Attribute.attributeDestroy' on
      each value and @/g_slist_free()/@ on the list. -}
    attrIteratorGetAttrs iterator = liftIO $ do
        iterator' <- unsafeManagedPtrGetPtr iterator
        result <- pango_attr_iterator_get_attrs iterator'
        result' <- unpackGSList result
        result'' <- mapM (wrapPtr Pango.Attribute.Attribute) result'
        g_slist_free result
        touchManagedPtr iterator
        return result''

    #if ENABLE_OVERLOADING
    data AttrIteratorGetAttrsMethodInfo
    instance (signature ~ (m [Pango.Attribute.Attribute]), MonadIO m) => O.MethodInfo AttrIteratorGetAttrsMethodInfo AttrIterator signature where
        overloadedMethod _ = attrIteratorGetAttrs

    #endif

    -- method AttrIterator::get_font
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "iterator", argType = TInterface (Name {namespace = "Pango", name = "AttrIterator"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #PangoAttrIterator", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "desc", argType = TInterface (Name {namespace = "Pango", name = "FontDescription"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #PangoFontDescription to fill in with the current values.\n       The family name in this structure will be set using\n       pango_font_description_set_family_static() using values from\n       an attribute in the #PangoAttrList associated with the iterator,\n       so if you plan to keep it around, you must call:\n       <literal>pango_font_description_set_family (desc, pango_font_description_get_family (desc))</literal>.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "language", argType = TInterface (Name {namespace = "Pango", name = "Language"}), direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "if non-%NULL, location to store language tag for item, or %NULL\n           if none is found.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "extra_attrs", argType = TGSList (TInterface (Name {namespace = "Pango", name = "Attribute"})), direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "if non-%NULL,\n          location in which to store a list of non-font\n          attributes at the the current position; only the highest priority\n          value of each attribute will be added to this list. In order\n          to free this value, you must call pango_attribute_destroy() on\n          each member.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferEverything}]
    -- Lengths : []
    -- returnType : Nothing
    -- throws : False
    -- Skip return : False

    foreign import ccall "pango_attr_iterator_get_font" pango_attr_iterator_get_font ::
        Ptr AttrIterator ->                     -- iterator : TInterface (Name {namespace = "Pango", name = "AttrIterator"})
        Ptr Pango.FontDescription.FontDescription -> -- desc : TInterface (Name {namespace = "Pango", name = "FontDescription"})
        Ptr Pango.Language.Language ->          -- language : TInterface (Name {namespace = "Pango", name = "Language"})
        Ptr (GSList (Ptr Pango.Attribute.Attribute)) -> -- extra_attrs : TGSList (TInterface (Name {namespace = "Pango", name = "Attribute"}))
        IO ()

    {- |
    Get the font and other attributes at the current iterator position.
    -}
    attrIteratorGetFont ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        AttrIterator
        {- ^ /@iterator@/: a 'GI.Pango.Structs.AttrIterator.AttrIterator' -}
        -> Pango.FontDescription.FontDescription
        {- ^ /@desc@/: a 'GI.Pango.Structs.FontDescription.FontDescription' to fill in with the current values.
           The family name in this structure will be set using
           'GI.Pango.Structs.FontDescription.fontDescriptionSetFamilyStatic' using values from
           an attribute in the 'GI.Pango.Structs.AttrList.AttrList' associated with the iterator,
           so if you plan to keep it around, you must call:
           \<literal>pango_font_description_set_family (desc, pango_font_description_get_family (desc))\<\/literal>. -}
        -> Maybe (Pango.Language.Language)
        {- ^ /@language@/: if non-'Nothing', location to store language tag for item, or 'Nothing'
               if none is found. -}
        -> [Pango.Attribute.Attribute]
        {- ^ /@extraAttrs@/: if non-'Nothing',
              location in which to store a list of non-font
              attributes at the the current position; only the highest priority
              value of each attribute will be added to this list. In order
              to free this value, you must call 'GI.Pango.Structs.Attribute.attributeDestroy' on
              each member. -}
        -> m ()
    attrIteratorGetFont iterator desc language extraAttrs = liftIO $ do
        iterator' <- unsafeManagedPtrGetPtr iterator
        desc' <- unsafeManagedPtrGetPtr desc
        maybeLanguage <- case language of
            Nothing -> return nullPtr
            Just jLanguage -> do
                jLanguage' <- unsafeManagedPtrGetPtr jLanguage
                return jLanguage'
        extraAttrs' <- mapM unsafeManagedPtrGetPtr extraAttrs
        extraAttrs'' <- packGSList extraAttrs'
        pango_attr_iterator_get_font iterator' desc' maybeLanguage extraAttrs''
        touchManagedPtr iterator
        touchManagedPtr desc
        whenJust language touchManagedPtr
        mapM_ touchManagedPtr extraAttrs
        return ()

    #if ENABLE_OVERLOADING
    data AttrIteratorGetFontMethodInfo
    instance (signature ~ (Pango.FontDescription.FontDescription -> Maybe (Pango.Language.Language) -> [Pango.Attribute.Attribute] -> m ()), MonadIO m) => O.MethodInfo AttrIteratorGetFontMethodInfo AttrIterator signature where
        overloadedMethod _ = attrIteratorGetFont

    #endif

    -- method AttrIterator::next
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "iterator", argType = TInterface (Name {namespace = "Pango", name = "AttrIterator"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #PangoAttrIterator", 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 "pango_attr_iterator_next" pango_attr_iterator_next ::
        Ptr AttrIterator ->                     -- iterator : TInterface (Name {namespace = "Pango", name = "AttrIterator"})
        IO CInt

    {- |
    Advance the iterator until the next change of style.
    -}
    attrIteratorNext ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        AttrIterator
        {- ^ /@iterator@/: a 'GI.Pango.Structs.AttrIterator.AttrIterator' -}
        -> m Bool
        {- ^ __Returns:__ 'False' if the iterator is at the end of the list, otherwise 'True' -}
    attrIteratorNext iterator = liftIO $ do
        iterator' <- unsafeManagedPtrGetPtr iterator
        result <- pango_attr_iterator_next iterator'
        let result' = (/= 0) result
        touchManagedPtr iterator
        return result'

    #if ENABLE_OVERLOADING
    data AttrIteratorNextMethodInfo
    instance (signature ~ (m Bool), MonadIO m) => O.MethodInfo AttrIteratorNextMethodInfo AttrIterator signature where
        overloadedMethod _ = attrIteratorNext

    #endif

    -- method AttrIterator::range
    -- method type : OrdinaryMethod
    -- Args : [Arg {argCName = "iterator", argType = TInterface (Name {namespace = "Pango", name = "AttrIterator"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #PangoAttrIterator", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "start", argType = TBasicType TInt, direction = DirectionOut, mayBeNull = False, argDoc = Documentation {rawDocText = Just "location to store the start of the range", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferEverything},Arg {argCName = "end", argType = TBasicType TInt, direction = DirectionOut, mayBeNull = False, argDoc = Documentation {rawDocText = Just "location to store the end of the range", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferEverything}]
    -- Lengths : []
    -- returnType : Nothing
    -- throws : False
    -- Skip return : False

    foreign import ccall "pango_attr_iterator_range" pango_attr_iterator_range ::
        Ptr AttrIterator ->                     -- iterator : TInterface (Name {namespace = "Pango", name = "AttrIterator"})
        Ptr Int32 ->                            -- start : TBasicType TInt
        Ptr Int32 ->                            -- end : TBasicType TInt
        IO ()

    {- |
    Get the range of the current segment. Note that the
    stored return values are signed, not unsigned like
    the values in 'GI.Pango.Structs.Attribute.Attribute'. To deal with this API
    oversight, stored return values that wouldn\'t fit into
    a signed integer are clamped to @/G_MAXINT/@.
    -}
    attrIteratorRange ::
        (B.CallStack.HasCallStack, MonadIO m) =>
        AttrIterator
        {- ^ /@iterator@/: a 'GI.Pango.Structs.AttrIterator.AttrIterator' -}
        -> m ((Int32, Int32))
    attrIteratorRange iterator = liftIO $ do
        iterator' <- unsafeManagedPtrGetPtr iterator
        start <- allocMem :: IO (Ptr Int32)
        end <- allocMem :: IO (Ptr Int32)
        pango_attr_iterator_range iterator' start end
        start' <- peek start
        end' <- peek end
        touchManagedPtr iterator
        freeMem start
        freeMem end
        return (start', end')

    #if ENABLE_OVERLOADING
    data AttrIteratorRangeMethodInfo
    instance (signature ~ (m ((Int32, Int32))), MonadIO m) => O.MethodInfo AttrIteratorRangeMethodInfo AttrIterator signature where
        overloadedMethod _ = attrIteratorRange

    #endif

    #if ENABLE_OVERLOADING
    type family ResolveAttrIteratorMethod (t :: Symbol) (o :: *) :: * where
        ResolveAttrIteratorMethod "destroy" o = AttrIteratorDestroyMethodInfo
        ResolveAttrIteratorMethod "next" o = AttrIteratorNextMethodInfo
        ResolveAttrIteratorMethod "range" o = AttrIteratorRangeMethodInfo
        ResolveAttrIteratorMethod "getAttrs" o = AttrIteratorGetAttrsMethodInfo
        ResolveAttrIteratorMethod "getFont" o = AttrIteratorGetFontMethodInfo
        ResolveAttrIteratorMethod l o = O.MethodResolutionFailed l o

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

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