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

Represents a tree object.
-}

#define ENABLE_OVERLOADING (MIN_VERSION_haskell_gi_overloading(1,0,0) \
       && !defined(__HADDOCK_VERSION__))

module GI.Ggit.Objects.Tree
    (

-- * Exported types
    Tree(..)                                ,
    IsTree                                  ,
    toTree                                  ,
    noTree                                  ,


 -- * Methods
-- ** get #method:get#

#if ENABLE_OVERLOADING
    TreeGetMethodInfo                       ,
#endif
    treeGet                                 ,


-- ** getByName #method:getByName#

#if ENABLE_OVERLOADING
    TreeGetByNameMethodInfo                 ,
#endif
    treeGetByName                           ,


-- ** getByPath #method:getByPath#

#if ENABLE_OVERLOADING
    TreeGetByPathMethodInfo                 ,
#endif
    treeGetByPath                           ,


-- ** getId #method:getId#

#if ENABLE_OVERLOADING
    TreeGetIdMethodInfo                     ,
#endif
    treeGetId                               ,


-- ** size #method:size#

#if ENABLE_OVERLOADING
    TreeSizeMethodInfo                      ,
#endif
    treeSize                                ,


-- ** walk #method:walk#

#if ENABLE_OVERLOADING
    TreeWalkMethodInfo                      ,
#endif
    treeWalk                                ,




    ) 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.GClosure as B.GClosure
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.GI.Base.Properties as B.Properties
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 GHC.OverloadedLabels as OL

import qualified GI.GObject.Objects.Object as GObject.Object
import qualified GI.Ggit.Callbacks as Ggit.Callbacks
import {-# SOURCE #-} qualified GI.Ggit.Enums as Ggit.Enums
import {-# SOURCE #-} qualified GI.Ggit.Objects.Native as Ggit.Native
import {-# SOURCE #-} qualified GI.Ggit.Objects.Object as Ggit.Object
import {-# SOURCE #-} qualified GI.Ggit.Objects.ObjectFactoryBase as Ggit.ObjectFactoryBase
import {-# SOURCE #-} qualified GI.Ggit.Structs.OId as Ggit.OId
import {-# SOURCE #-} qualified GI.Ggit.Structs.TreeEntry as Ggit.TreeEntry

-- | Memory-managed wrapper type.
newtype Tree = Tree (ManagedPtr Tree)
foreign import ccall "ggit_tree_get_type"
    c_ggit_tree_get_type :: IO GType

instance GObject Tree where
    gobjectType = c_ggit_tree_get_type


-- | Type class for types which can be safely cast to `Tree`, for instance with `toTree`.
class (GObject o, O.IsDescendantOf Tree o) => IsTree o
instance (GObject o, O.IsDescendantOf Tree o) => IsTree o

instance O.HasParentTypes Tree
type instance O.ParentTypes Tree = '[Ggit.Object.Object, Ggit.Native.Native, Ggit.ObjectFactoryBase.ObjectFactoryBase, GObject.Object.Object]

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

-- | A convenience alias for `Nothing` :: `Maybe` `Tree`.
noTree :: Maybe Tree
noTree = Nothing

#if ENABLE_OVERLOADING
type family ResolveTreeMethod (t :: Symbol) (o :: *) :: * where
    ResolveTreeMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
    ResolveTreeMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
    ResolveTreeMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
    ResolveTreeMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
    ResolveTreeMethod "get" o = TreeGetMethodInfo
    ResolveTreeMethod "getv" o = GObject.Object.ObjectGetvMethodInfo
    ResolveTreeMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
    ResolveTreeMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
    ResolveTreeMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
    ResolveTreeMethod "ref" o = GObject.Object.ObjectRefMethodInfo
    ResolveTreeMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
    ResolveTreeMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
    ResolveTreeMethod "size" o = TreeSizeMethodInfo
    ResolveTreeMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
    ResolveTreeMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
    ResolveTreeMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
    ResolveTreeMethod "unref" o = GObject.Object.ObjectUnrefMethodInfo
    ResolveTreeMethod "walk" o = TreeWalkMethodInfo
    ResolveTreeMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
    ResolveTreeMethod "getByName" o = TreeGetByNameMethodInfo
    ResolveTreeMethod "getByPath" o = TreeGetByPathMethodInfo
    ResolveTreeMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
    ResolveTreeMethod "getId" o = TreeGetIdMethodInfo
    ResolveTreeMethod "getOwner" o = Ggit.Object.ObjectGetOwnerMethodInfo
    ResolveTreeMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
    ResolveTreeMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
    ResolveTreeMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
    ResolveTreeMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
    ResolveTreeMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveTreeMethod t Tree, O.MethodInfo info Tree p) => OL.IsLabel t (Tree -> 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

#if ENABLE_OVERLOADING
instance O.HasAttributeList Tree
type instance O.AttributeList Tree = TreeAttributeList
type TreeAttributeList = ('[ '("native", Ggit.Native.NativeNativePropertyInfo)] :: [(Symbol, *)])
#endif

#if ENABLE_OVERLOADING
#endif

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

#endif

-- method Tree::get
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "tree", argType = TInterface (Name {namespace = "Ggit", name = "Tree"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GgitTree.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "i", argType = TBasicType TUInt, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the index of the entry.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Ggit", name = "TreeEntry"}))
-- throws : False
-- Skip return : False

foreign import ccall "ggit_tree_get" ggit_tree_get ::
    Ptr Tree ->                             -- tree : TInterface (Name {namespace = "Ggit", name = "Tree"})
    Word32 ->                               -- i : TBasicType TUInt
    IO (Ptr Ggit.TreeEntry.TreeEntry)

{- |
Get a tree entry by index.
-}
treeGet ::
    (B.CallStack.HasCallStack, MonadIO m, IsTree a) =>
    a
    {- ^ /@tree@/: a 'GI.Ggit.Objects.Tree.Tree'. -}
    -> Word32
    {- ^ /@i@/: the index of the entry. -}
    -> m (Maybe Ggit.TreeEntry.TreeEntry)
    {- ^ __Returns:__ a 'GI.Ggit.Structs.TreeEntry.TreeEntry' or 'Nothing'. -}
treeGet tree i = liftIO $ do
    tree' <- unsafeManagedPtrCastPtr tree
    result <- ggit_tree_get tree' i
    maybeResult <- convertIfNonNull result $ \result' -> do
        result'' <- (wrapBoxed Ggit.TreeEntry.TreeEntry) result'
        return result''
    touchManagedPtr tree
    return maybeResult

#if ENABLE_OVERLOADING
data TreeGetMethodInfo
instance (signature ~ (Word32 -> m (Maybe Ggit.TreeEntry.TreeEntry)), MonadIO m, IsTree a) => O.MethodInfo TreeGetMethodInfo a signature where
    overloadedMethod _ = treeGet

#endif

-- method Tree::get_by_name
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "tree", argType = TInterface (Name {namespace = "Ggit", name = "Tree"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GgitTree.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "name", argType = TBasicType TUTF8, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a filename.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Ggit", name = "TreeEntry"}))
-- throws : False
-- Skip return : False

foreign import ccall "ggit_tree_get_by_name" ggit_tree_get_by_name ::
    Ptr Tree ->                             -- tree : TInterface (Name {namespace = "Ggit", name = "Tree"})
    CString ->                              -- name : TBasicType TUTF8
    IO (Ptr Ggit.TreeEntry.TreeEntry)

{- |
Get a tree entry by name.
-}
treeGetByName ::
    (B.CallStack.HasCallStack, MonadIO m, IsTree a) =>
    a
    {- ^ /@tree@/: a 'GI.Ggit.Objects.Tree.Tree'. -}
    -> T.Text
    {- ^ /@name@/: a filename. -}
    -> m (Maybe Ggit.TreeEntry.TreeEntry)
    {- ^ __Returns:__ a 'GI.Ggit.Structs.TreeEntry.TreeEntry' or 'Nothing'. -}
treeGetByName tree name = liftIO $ do
    tree' <- unsafeManagedPtrCastPtr tree
    name' <- textToCString name
    result <- ggit_tree_get_by_name tree' name'
    maybeResult <- convertIfNonNull result $ \result' -> do
        result'' <- (wrapBoxed Ggit.TreeEntry.TreeEntry) result'
        return result''
    touchManagedPtr tree
    freeMem name'
    return maybeResult

#if ENABLE_OVERLOADING
data TreeGetByNameMethodInfo
instance (signature ~ (T.Text -> m (Maybe Ggit.TreeEntry.TreeEntry)), MonadIO m, IsTree a) => O.MethodInfo TreeGetByNameMethodInfo a signature where
    overloadedMethod _ = treeGetByName

#endif

-- method Tree::get_by_path
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "tree", argType = TInterface (Name {namespace = "Ggit", name = "Tree"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GgitTree.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "path", argType = TBasicType TUTF8, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a path.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Ggit", name = "TreeEntry"}))
-- throws : True
-- Skip return : False

foreign import ccall "ggit_tree_get_by_path" ggit_tree_get_by_path ::
    Ptr Tree ->                             -- tree : TInterface (Name {namespace = "Ggit", name = "Tree"})
    CString ->                              -- path : TBasicType TUTF8
    Ptr (Ptr GError) ->                     -- error
    IO (Ptr Ggit.TreeEntry.TreeEntry)

{- |
Retrieves a tree entry contained in a tree or in any of its subtrees,
given its relative path.
-}
treeGetByPath ::
    (B.CallStack.HasCallStack, MonadIO m, IsTree a) =>
    a
    {- ^ /@tree@/: a 'GI.Ggit.Objects.Tree.Tree'. -}
    -> T.Text
    {- ^ /@path@/: a path. -}
    -> m (Maybe Ggit.TreeEntry.TreeEntry)
    {- ^ __Returns:__ a 'GI.Ggit.Structs.TreeEntry.TreeEntry' or 'Nothing'. /(Can throw 'Data.GI.Base.GError.GError')/ -}
treeGetByPath tree path = liftIO $ do
    tree' <- unsafeManagedPtrCastPtr tree
    path' <- textToCString path
    onException (do
        result <- propagateGError $ ggit_tree_get_by_path tree' path'
        maybeResult <- convertIfNonNull result $ \result' -> do
            result'' <- (wrapBoxed Ggit.TreeEntry.TreeEntry) result'
            return result''
        touchManagedPtr tree
        freeMem path'
        return maybeResult
     ) (do
        freeMem path'
     )

#if ENABLE_OVERLOADING
data TreeGetByPathMethodInfo
instance (signature ~ (T.Text -> m (Maybe Ggit.TreeEntry.TreeEntry)), MonadIO m, IsTree a) => O.MethodInfo TreeGetByPathMethodInfo a signature where
    overloadedMethod _ = treeGetByPath

#endif

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

foreign import ccall "ggit_tree_get_id" ggit_tree_get_id ::
    Ptr Tree ->                             -- tree : TInterface (Name {namespace = "Ggit", name = "Tree"})
    IO (Ptr Ggit.OId.OId)

{- |
Get the 'GI.Ggit.Structs.OId.OId' of the tree.
-}
treeGetId ::
    (B.CallStack.HasCallStack, MonadIO m, IsTree a) =>
    a
    {- ^ /@tree@/: a 'GI.Ggit.Objects.Tree.Tree'. -}
    -> m (Maybe Ggit.OId.OId)
    {- ^ __Returns:__ a 'GI.Ggit.Structs.OId.OId' or 'Nothing'. -}
treeGetId tree = liftIO $ do
    tree' <- unsafeManagedPtrCastPtr tree
    result <- ggit_tree_get_id tree'
    maybeResult <- convertIfNonNull result $ \result' -> do
        result'' <- (wrapBoxed Ggit.OId.OId) result'
        return result''
    touchManagedPtr tree
    return maybeResult

#if ENABLE_OVERLOADING
data TreeGetIdMethodInfo
instance (signature ~ (m (Maybe Ggit.OId.OId)), MonadIO m, IsTree a) => O.MethodInfo TreeGetIdMethodInfo a signature where
    overloadedMethod _ = treeGetId

#endif

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

foreign import ccall "ggit_tree_size" ggit_tree_size ::
    Ptr Tree ->                             -- tree : TInterface (Name {namespace = "Ggit", name = "Tree"})
    IO Word32

{- |
Get the number of entries in the tree.
-}
treeSize ::
    (B.CallStack.HasCallStack, MonadIO m, IsTree a) =>
    a
    {- ^ /@tree@/: a 'GI.Ggit.Objects.Tree.Tree'. -}
    -> m Word32
    {- ^ __Returns:__ the number of entries in the tree. -}
treeSize tree = liftIO $ do
    tree' <- unsafeManagedPtrCastPtr tree
    result <- ggit_tree_size tree'
    touchManagedPtr tree
    return result

#if ENABLE_OVERLOADING
data TreeSizeMethodInfo
instance (signature ~ (m Word32), MonadIO m, IsTree a) => O.MethodInfo TreeSizeMethodInfo a signature where
    overloadedMethod _ = treeSize

#endif

-- method Tree::walk
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "tree", argType = TInterface (Name {namespace = "Ggit", name = "Tree"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GgitTree.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "mode", argType = TInterface (Name {namespace = "Ggit", name = "TreeWalkMode"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the walking order.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "callback", argType = TInterface (Name {namespace = "Ggit", name = "TreeWalkCallback"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the callback to call for each entry.", sinceVersion = Nothing}, argScope = ScopeTypeCall, argClosure = 3, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "user_data", argType = TBasicType TPtr, direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "user data for the callback.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : True
-- Skip return : False

foreign import ccall "ggit_tree_walk" ggit_tree_walk ::
    Ptr Tree ->                             -- tree : TInterface (Name {namespace = "Ggit", name = "Tree"})
    CUInt ->                                -- mode : TInterface (Name {namespace = "Ggit", name = "TreeWalkMode"})
    FunPtr Ggit.Callbacks.C_TreeWalkCallback -> -- callback : TInterface (Name {namespace = "Ggit", name = "TreeWalkCallback"})
    Ptr () ->                               -- user_data : TBasicType TPtr
    Ptr (Ptr GError) ->                     -- error
    IO ()

{- |
Walk all the entries of a tree object recursively (resolving and walking
subtrees of the tree as needed). The /@error@/ will be set to the error returned
by /@callback@/ (if any).
-}
treeWalk ::
    (B.CallStack.HasCallStack, MonadIO m, IsTree a) =>
    a
    {- ^ /@tree@/: a 'GI.Ggit.Objects.Tree.Tree'. -}
    -> Ggit.Enums.TreeWalkMode
    {- ^ /@mode@/: the walking order. -}
    -> Ggit.Callbacks.TreeWalkCallback
    {- ^ /@callback@/: the callback to call for each entry. -}
    -> m ()
    {- ^ /(Can throw 'Data.GI.Base.GError.GError')/ -}
treeWalk tree mode callback = liftIO $ do
    tree' <- unsafeManagedPtrCastPtr tree
    let mode' = (fromIntegral . fromEnum) mode
    callback' <- Ggit.Callbacks.mk_TreeWalkCallback (Ggit.Callbacks.wrap_TreeWalkCallback Nothing (Ggit.Callbacks.drop_closures_TreeWalkCallback callback))
    let userData = nullPtr
    onException (do
        propagateGError $ ggit_tree_walk tree' mode' callback' userData
        safeFreeFunPtr $ castFunPtrToPtr callback'
        touchManagedPtr tree
        return ()
     ) (do
        safeFreeFunPtr $ castFunPtrToPtr callback'
        return ()
     )

#if ENABLE_OVERLOADING
data TreeWalkMethodInfo
instance (signature ~ (Ggit.Enums.TreeWalkMode -> Ggit.Callbacks.TreeWalkCallback -> m ()), MonadIO m, IsTree a) => O.MethodInfo TreeWalkMethodInfo a signature where
    overloadedMethod _ = treeWalk

#endif