module Graphics.Gloss.Interface.FRP.ReactiveBanana (playBanana, InputEvent) where

import Graphics.Gloss
import Graphics.Gloss.Interface.IO.Game (playIO)
import qualified Graphics.Gloss.Interface.IO.Game as G
import Reactive.Banana
import Reactive.Banana.Frameworks
import Data.IORef (IORef, newIORef, readIORef, writeIORef)

-- | A useful type synonym for Gloss event values, to avoid confusion between
--   Gloss and ReactiveBanana.
type InputEvent = G.Event

-- | Play the game in a window, updating when the value of the provided
--   Behavior t Picture changes.
playBanana  Display -- ^ The display method
            Color   -- ^ The background colour
            Int     -- ^ The refresh rate, in Hertz
            ( t. Frameworks t
               Event t Float
               Event t InputEvent
               Moment t (Behavior t Picture))
           -- ^ A Moment t action to generate the Picture Behavior, taking
           --   the refresh and input Events with respect to which to build it.
           --   The refresh event generates a Float indicating the time delta
           --   since the last refresh.
            IO ()
playBanana display colour frequency mPicture = do
  pictureref  newIORef blank
  (tickHandler,  tick)   newAddHandler
  (eventHandler, event)  newAddHandler
  compile (makeNetwork tickHandler eventHandler $ change pictureref) >>= actuate
  playIO display colour frequency ()
    (\      _  readIORef pictureref)
    (\ ev   _  () <$ event ev)
    (\ time _  () <$ tick time)
    change  IORef Picture  Picture  IO ()
    change pictureref picture = do
      writeIORef pictureref picture
    makeNetwork tickHandler eventHandler change = do
      eTick   fromAddHandler tickHandler
      eEvent  fromAddHandler eventHandler
      bPicture  mPicture eTick eEvent
      changes bPicture >>= reactimate . fmap change
      initial bPicture >>= liftIO . change