{- |
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.
-}

module GI.Pango.Structs.AttrIterator
    ( 

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


 -- * Methods
-- ** destroy #method:destroy#
    AttrIteratorDestroyMethodInfo           ,
    attrIteratorDestroy                     ,


-- ** getAttrs #method:getAttrs#
    AttrIteratorGetAttrsMethodInfo          ,
    attrIteratorGetAttrs                    ,


-- ** getFont #method:getFont#
    AttrIteratorGetFontMethodInfo           ,
    attrIteratorGetFont                     ,


-- ** next #method:next#
    AttrIteratorNextMethodInfo              ,
    attrIteratorNext                        ,


-- ** range #method:range#
    AttrIteratorRangeMethodInfo             ,
    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.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

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

noAttrIterator :: Maybe AttrIterator
noAttrIterator = Nothing


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

-- 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 ()

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

-- 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''

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

-- 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 ()

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

-- 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'

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

-- 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')

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

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
    fromLabel _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
#endif