-- GENERATED by C->Haskell Compiler, version 0.28.3 Switcheroo, 25 November 2017 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "src/Chiphunk/Low/Callback.chs" #-}
-- | Description: Collision handler definition
-- Module provides definitions for collision handlers.
module Chiphunk.Low.Callback
  ( CollisionCallback
  , CollisionHandler (..)
  , CollisionHandlerPtr
  , spaceAddCollisionHandler
  , spaceAddWildcardHandler
  , spaceAddDefaultCollisionHandler
  , modifyCollisionHandler
  , mkCallback
  , mkCallbackB
  , PostStepFunc
  , spaceAddPostStepCallback
  ) where
import qualified Foreign.C.Types as C2HSImp
import qualified Foreign.Marshal.Utils as C2HSImp
import qualified Foreign.Ptr as C2HSImp
import qualified Foreign.Storable as C2HSImp



import Control.Applicative (liftA)
import Control.Exception.Safe
import Data.Bool (bool)
import Foreign

import Chiphunk.Low.Types
{-# LINE 22 "src/Chiphunk/Low/Callback.chs" #-}




-- | Collision callback
type CollisionCallback ret = Arbiter -> Space -> DataPtr -> IO ret

-- | This collision handler processes collisions between objects of type @typeA@ and @typeB@.
-- Fill the desired collision callback functions- they are documented above. A user definable context pointer
-- @userData@ is included for your convenience. This pointer is provided as an argument in each callback function.
--
-- A collision handler is a set of 4 function callbacks for the different collision events that Chipmunk recognizes.
data CollisionHandler = CollisionHandler
  { chTypeA         :: !CollisionType                   -- ^ typeA
  , chTypeB         :: !CollisionType                   -- ^ typeB
  , chBeginFunc     :: !(FunPtr (CollisionCallback CPBool))
    -- ^ Two shapes just started touching for the first time this step. Return true from the callback
    -- to process the collision normally or false to cause Chipmunk to ignore the collision entirely.
    -- If you return false, the preSolve and postSolve callbacks will never be run, but you will still recieve
    -- a separate event when the shapes stop overlapping.
  , chPreSolveFunc  :: !(FunPtr (CollisionCallback CPBool))
    -- ^ Two shapes are touching during this step. Return false from the callback to make Chipmunk ignore the collision
    -- this step or true to process it normally. Additionally, you may override collision values using
    -- 'Chiphunk.Low.Arbiter.arbiterFriction', 'Chiphunk.Low.Arbiter.arbiterRestitution' or
    -- 'Chiphunk.Low.arbiterSurfaceVelocity' to provide custom friction, elasticity, or surface velocity values.
    -- See 'Arbiter' for more info.
  , chPostSolveFunc :: !(FunPtr (CollisionCallback ()))
    -- ^ Two shapes are touching and their collision response has been processed. You can retrieve the collision
    -- impulse or kinetic energy at this time if you want to use it to calculate sound volumes or damage amounts.
    -- See 'Arbiter' for more info.
  , chSeparateFunc  :: !(FunPtr (CollisionCallback ()))
    -- ^ Two shapes have just stopped touching for the first time this step. To ensure that begin/separate
    -- are always called in balanced pairs, it will also be called when removing a shape while its in contact
    -- with something or when deallocating the space.
  , cpUserData      :: !DataPtr                         -- ^ userData
  } deriving Show

instance Storable CollisionHandler where
  sizeOf _ = 56
{-# LINE 60 "src/Chiphunk/Low/Callback.chs" #-}

  alignment _ = 8
{-# LINE 61 "src/Chiphunk/Low/Callback.chs" #-}

  poke p (CollisionHandler typA typB beginFunc preSolveFunc postSolveFunc separateFunc userData) = do
    (\ptr val -> do {C2HSImp.pokeByteOff ptr 0 (val :: C2HSImp.CULong)}) p $ fromIntegral typA
    (\ptr val -> do {C2HSImp.pokeByteOff ptr 8 (val :: C2HSImp.CULong)}) p $ fromIntegral typB
    (\ptr val -> do {C2HSImp.pokeByteOff ptr 16 (val :: (C2HSImp.FunPtr ((Arbiter) -> ((Space) -> ((DataPtr) -> (IO C2HSImp.CUChar))))))}) p beginFunc
    (\ptr val -> do {C2HSImp.pokeByteOff ptr 24 (val :: (C2HSImp.FunPtr ((Arbiter) -> ((Space) -> ((DataPtr) -> (IO C2HSImp.CUChar))))))}) p preSolveFunc
    (\ptr val -> do {C2HSImp.pokeByteOff ptr 32 (val :: (C2HSImp.FunPtr ((Arbiter) -> ((Space) -> ((DataPtr) -> (IO ()))))))}) p postSolveFunc
    (\ptr val -> do {C2HSImp.pokeByteOff ptr 40 (val :: (C2HSImp.FunPtr ((Arbiter) -> ((Space) -> ((DataPtr) -> (IO ()))))))}) p separateFunc
    (\ptr val -> do {C2HSImp.pokeByteOff ptr 48 (val :: (C2HSImp.Ptr ()))}) p userData
  peek p = CollisionHandler <$> (fromIntegral <$> (\ptr -> do {C2HSImp.peekByteOff ptr 0 :: IO C2HSImp.CULong}) p)
                            <*> (fromIntegral <$> (\ptr -> do {C2HSImp.peekByteOff ptr 8 :: IO C2HSImp.CULong}) p)
                            <*> (\ptr -> do {C2HSImp.peekByteOff ptr 16 :: IO (C2HSImp.FunPtr ((Arbiter) -> ((Space) -> ((DataPtr) -> (IO C2HSImp.CUChar)))))}) p
                            <*> (\ptr -> do {C2HSImp.peekByteOff ptr 24 :: IO (C2HSImp.FunPtr ((Arbiter) -> ((Space) -> ((DataPtr) -> (IO C2HSImp.CUChar)))))}) p
                            <*> (\ptr -> do {C2HSImp.peekByteOff ptr 32 :: IO (C2HSImp.FunPtr ((Arbiter) -> ((Space) -> ((DataPtr) -> (IO ())))))}) p
                            <*> (\ptr -> do {C2HSImp.peekByteOff ptr 40 :: IO (C2HSImp.FunPtr ((Arbiter) -> ((Space) -> ((DataPtr) -> (IO ())))))}) p
                            <*> (\ptr -> do {C2HSImp.peekByteOff ptr 48 :: IO (C2HSImp.Ptr ())}) p

foreign import ccall unsafe "wrapper"
  mkCallback' :: CollisionCallback () -> IO (FunPtr (CollisionCallback ()))

-- | Make callback. Need to free afterwards.
mkCallback :: CollisionCallback () -> IO (FunPtr (CollisionCallback ()))
mkCallback = mkCallback'

foreign import ccall unsafe "wrapper"
  mkCallbackB' :: CollisionCallback CPBool -> IO (FunPtr (CollisionCallback CPBool))

-- | Make callback. Need to free afterwards.
mkCallbackB :: CollisionCallback Bool -> IO (FunPtr (CollisionCallback CPBool))
mkCallbackB = mkCallbackB' . liftA (liftA $ liftA $ liftA $ bool 0 1)

-- | Pointer to collision handler
type CollisionHandlerPtr = C2HSImp.Ptr (CollisionHandler)
{-# LINE 93 "src/Chiphunk/Low/Callback.chs" #-}


-- | Add a 'CollisionHandler' for specific collision type pair or return the existing handler for the type pair.
-- Whenever shapes with collision types (cpShape.collision_type) a and b collide,
-- this handler will be used to process the collision events. When a new collision handler is created,
-- the callbacks will all be set to builtin callbacks that perform the default behavior
-- (call the wildcard handlers, and accept all collisions).
spaceAddCollisionHandler :: (Space) -> (CollisionType) -- ^ a
 -> (CollisionType) -- ^ b
 -> IO ((CollisionHandlerPtr))
spaceAddCollisionHandler a1 a2 a3 =
  let {a1' = id a1} in
  let {a2' = fromIntegral a2} in
  let {a3' = fromIntegral a3} in
  spaceAddCollisionHandler'_ a1' a2' a3' >>= \res ->
  let {res' = id res} in
  return (res')

{-# LINE 104 "src/Chiphunk/Low/Callback.chs" #-}


-- | Add a wildcard collision handler for given collision type. This handler will be used any time an object
-- with this type collides with another object, regardless of its type. A good example is a projectile
-- that should be destroyed the first time it hits anything. There may be a specific collision handler
-- and two wildcard handlers. It’s up to the specific handler to decide if and when to call the wildcard handlers
-- and what to do with their return values. (See arbiterCallWildcard* below)
-- When a new wildcard handler is created, the callbacks will all be set to builtin callbacks
-- that perform the default behavior. (accept all collisions in begin and preSolve, or do nothing for postSolve
-- and separate.
spaceAddWildcardHandler :: (Space) -> (CollisionType) -- ^ type
 -> IO ((CollisionHandlerPtr))
spaceAddWildcardHandler a1 a2 =
  let {a1' = id a1} in
  let {a2' = fromIntegral a2} in
  spaceAddWildcardHandler'_ a1' a2' >>= \res ->
  let {res' = id res} in
  return (res')

{-# LINE 117 "src/Chiphunk/Low/Callback.chs" #-}


-- | Return a reference to the default collision handler or that is used to process all collisions
-- that don’t have a more specific handler. The default behavior for each of the callbacks
-- is to call the wildcard handlers, ANDing their return values together if applicable.
spaceAddDefaultCollisionHandler :: (Space) -> IO ((CollisionHandlerPtr))
spaceAddDefaultCollisionHandler a1 =
  let {a1' = id a1} in
  spaceAddDefaultCollisionHandler'_ a1' >>= \res ->
  let {res' = id res} in
  return (res')

{-# LINE 124 "src/Chiphunk/Low/Callback.chs" #-}


-- | Use this helper function to modify collision handler.
--
-- @
-- spaceAddCollisionHandler s t1 t2 >>= flip modifyColliionHandler (\ch -> pure ch {chSeparateFunc = separateCollback})
-- @
modifyCollisionHandler :: CollisionHandlerPtr -> (CollisionHandler -> IO CollisionHandler) -> IO ()
modifyCollisionHandler chPtr inner = peek chPtr >>= inner >>= poke chPtr

-- | Function type used for postStep callbacks. @space@ is the space the callback was registered on,
-- @obj@ is the pointer value you supplied as the key, and @data@ is a user definable pointer you can use
-- to pass in as a context value.
type PostStepFunc
  = Space   -- ^ space
  -> Ptr () -- ^ obj
  -> Ptr () -- ^ data
  -> IO ()

foreign import ccall "wrapper"
  mkPostStep :: PostStepFunc -> IO (FunPtr PostStepFunc)

-- | Add @func@ to be called before 'spaceStep' returns. @key@ and @data@ will be passed to your function.
-- Only the first callback registered for any unique value of @key@ will be recorded.
--
-- It returns 'True' if the callback is scheduled and 'False' when the key has already been used.
--
-- __The behavior of adding a postStep callback from outside of a collision handler or query callback is undefined.__
spaceAddPostStepCallback :: (Space) -- ^ space
 -> (PostStepFunc) -- ^ func
 -> (Ptr ()) -- ^ key
 -> (Ptr ()) -- ^ data
 -> IO ((Bool))
spaceAddPostStepCallback a1 a2 a3 a4 =
  let {a1' = id a1} in
  mk a2 $ \a2' ->
  let {a3' = id a3} in
  let {a4' = id a4} in
  spaceAddPostStepCallback'_ a1' a2' a3' a4' >>= \res ->
  let {res' = C2HSImp.toBool res} in
  return (res')

{-# LINE 157 "src/Chiphunk/Low/Callback.chs" #-}

  where
    mk f = mkPostStep f `bracket` freeHaskellFunPtr

foreign import ccall unsafe "Chiphunk/Low/Callback.chs.h cpSpaceAddCollisionHandler"
  spaceAddCollisionHandler'_ :: ((Space) -> (C2HSImp.CULong -> (C2HSImp.CULong -> (IO (CollisionHandlerPtr)))))

foreign import ccall unsafe "Chiphunk/Low/Callback.chs.h cpSpaceAddWildcardHandler"
  spaceAddWildcardHandler'_ :: ((Space) -> (C2HSImp.CULong -> (IO (CollisionHandlerPtr))))

foreign import ccall unsafe "Chiphunk/Low/Callback.chs.h cpSpaceAddDefaultCollisionHandler"
  spaceAddDefaultCollisionHandler'_ :: ((Space) -> (IO (CollisionHandlerPtr)))

foreign import ccall unsafe "Chiphunk/Low/Callback.chs.h cpSpaceAddPostStepCallback"
  spaceAddPostStepCallback'_ :: ((Space) -> ((C2HSImp.FunPtr ((Space) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> (IO ()))))) -> ((C2HSImp.Ptr ()) -> ((C2HSImp.Ptr ()) -> (IO C2HSImp.CUChar)))))