-- | The simplest input: keypresses. Nice for testing.

module Midair.GetChar (
     runGetChar
   , GetChar(..)
   ) where

import Midair.Core
import Midair.Handy

import Control.Concurrent (forkIO, ThreadId)
import Control.Concurrent.STM
import Control.Monad
import System.IO (hSetBuffering, BufferMode(NoBuffering), stdin)


data GetChar = GetChar Char
 deriving (Show, Read, Eq, Ord)

runGetChar :: SFlow GetChar (Fx a) -> IO (ThreadId, ThreadId, SFNodeRef GetChar (Fx a))
runGetChar startGraph = do
   hSetBuffering stdin NoBuffering

   getCharTChan <- newTChanIO
   getCharTid <- forkIO $ forever $ do
      c <- getChar
      atomically $ writeTChan getCharTChan $ GetChar c

   wholeGraphRef <- mkNodeRef startGraph

   graphTVar <- newTVarIO $ nRef wholeGraphRef
   tid <- forkIO . forever . (runFx =<<) . atomically $
      readTChan getCharTChan >>= \msg -> do
         fireGraph graphTVar msg

   -- It's a good idea to return a ref of the whole graph so in
   -- case the user didn't make the node refs they ended up
   -- wanting, they can at least swap the whole thing out:
   return (getCharTid, tid, wholeGraphRef)