-- | In this module you will find methods to retrieve various sates from 'GeglNode's
module GEGL.Node.State
  ( gegl_node_get_consumers
  , gegl_node_get_producer
  , gegl_node_get_bounding_box
  ) where

import qualified GEGL.FFI.Node.State as FFI
import qualified GEGL.FFI.Node as FFI
import qualified GEGL.FFI.Rectangle as FFI

import Foreign.C.String
import Foreign.ForeignPtr
import Foreign.Marshal.Alloc (free)
import Foreign.Storable (peek)

-- | Retrieve which pads on which nodes are connected to a named output pad.
gegl_node_get_consumers
  :: FFI.GeglNode                -- ^ 'GeglNode' to retrieve from
  -> String                      -- ^ Name of the output pad
  -> IO [(FFI.GeglNode, String)] -- ^ List of consuming nodes
gegl_node_get_consumers (FFI.GeglNode node) name = do
  cname <- newCString name
  ptrs  <- withForeignPtr node $ \ptr -> FFI.c_gegl_node_get_consumers ptr cname
  nodes <- mapM (\nodePtr -> FFI.GeglNode <$> newForeignPtr_ (fst nodePtr)) ptrs
  names <- mapM (\nodePtr -> peekCString $ snd nodePtr) ptrs
  free cname
  return $ zip nodes names

gegl_node_get_producer
  :: FFI.GeglNode
  -> String
  -> IO (Maybe (FFI.GeglNode, String))
gegl_node_get_producer (FFI.GeglNode fnode) name = do
  cname <- newCString name
  mtup <- withForeignPtr fnode $ \node -> FFI.c_gegl_node_get_producer node cname
  free cname
  case mtup of
    Just (pnode, pcname) -> do
      pfnode <- FFI.GeglNode <$> newForeignPtr_ pnode
      pname  <- peekCString pcname
      return $ Just $ (pfnode, pname)
    Nothing ->
      return Nothing

-- | Get the bounding box of a 'GeglNode'
gegl_node_get_bounding_box
  :: FFI.GeglNode         -- ^ The 'GeglNode'
  -> IO FFI.GeglRectangle -- ^ resulting bounding box
gegl_node_get_bounding_box (FFI.GeglNode fnode) = do
  ptr <- withForeignPtr fnode $ \node -> FFI.c_gegl_node_get_bounding_box node
  rect <- peek ptr
  free ptr
  return rect