content: {-# LANGUAGE PackageImports #-}
  
  module Common.Utils where
  
  import Control.Applicative
  import Control.Monad
  import Data.Time.Clock
  import Graphics.UI.GLFW as GLFW
  import Graphics.Rendering.OpenGL.Raw.Core32 (glViewport)
  import FRP.Elerea.Param
  
  measureDuration :: IO a -> IO (NominalDiffTime, a)
  measureDuration action = do
      startTime <- getCurrentTime
      result <- action
      endTime <- getCurrentTime
      return (diffUTCTime endTime startTime, result)
  
  initWindow :: String -> Int -> Int -> IO (Window,Signal (Int, Int))
  initWindow title width height = do
      GLFW.init
      defaultWindowHints
      mapM_ windowHint
        [ WindowHint'ContextVersionMajor 3
        , WindowHint'ContextVersionMinor 3
        , WindowHint'OpenGLProfile OpenGLProfile'Core
        , WindowHint'OpenGLForwardCompat True
        ]
      Just win <- createWindow width height title Nothing Nothing
      makeContextCurrent $ Just win
  
      (windowSize, windowSizeSink) <- external (width, height)
      setWindowSizeCallback win $ Just $ \_ w h -> do
          glViewport 0 0 (fromIntegral w) (fromIntegral h)
          windowSizeSink (fromIntegral w, fromIntegral h)
  
      return (win,windowSize)
  
  driveNetwork :: (p -> IO (IO a)) -> IO (Maybe p) -> IO ()
  driveNetwork network driver = do
      dt <- driver
      case dt of
          Just dt -> do
              join (network dt)
              driveNetwork network driver
          Nothing -> return ()
  
  risingEdge :: Signal Bool -> SignalGen p (Signal Bool)
  risingEdge signal = do
      signal' <- delay True signal
      memo $ liftA2 (&&) signal (not <$> signal') 
  
  toggle :: Signal Bool -> SignalGen p (Signal Bool)
  toggle = transfer False (const (/=))
  