-- | Sometimes it is useful to be able to move nodes between graphs or even
-- handle orphaned nodes that are not part of a graph.
module GEGL.Reparent
  ( gegl_node_add_child
  , gegl_node_remove_child
  , gegl_node_get_parent
  )
where

import qualified GEGL.FFI.Reparent as FFI
import qualified GEGL.FFI.Node     as FFI

import System.Glib.GObject (objectUnref)

import Foreign.Ptr (nullPtr)
import Foreign.ForeignPtr (newForeignPtr, withForeignPtr)

-- | Make the Graph node take reference on the child node.
gegl_node_add_child
  :: FFI.GeglNode    -- ^ Graph node
  -> FFI.GeglNode    -- ^ Child node
  -> IO FFI.GeglNode -- ^ The child
gegl_node_add_child (FFI.GeglNode fgraph) (FFI.GeglNode fchild) =
  FFI.GeglNode <$> (newForeignPtr objectUnref =<<
    withForeignPtr fgraph (\graph ->
      withForeignPtr fchild (\child ->
        FFI.c_gegl_node_add_child graph child)))

-- | Removes a child form a 'FFI.GeglNode'.
gegl_node_remove_child
  :: FFI.GeglNode    -- ^ Graph node
  -> FFI.GeglNode    -- ^ Child node
  -> IO FFI.GeglNode -- ^ The child
gegl_node_remove_child (FFI.GeglNode fgraph) (FFI.GeglNode fchild) =
  FFI.GeglNode <$> (newForeignPtr objectUnref =<<
   withForeignPtr fgraph (\graph ->
     withForeignPtr fchild (\child ->
       FFI.c_gegl_node_remove_child graph child)))

-- | Gets parent of specified node. Returns 'Nothing' if node has no parent.
gegl_node_get_parent
  :: FFI.GeglNode            -- ^ A node
  -> IO (Maybe FFI.GeglNode) -- The parent node (if any)
gegl_node_get_parent (FFI.GeglNode fnode) = do
  ptr <- withForeignPtr fnode (\node -> FFI.c_gegl_node_get_parent node)
  if ptr == nullPtr
    then return Nothing
    else Just <$> FFI.GeglNode <$> newForeignPtr objectUnref ptr