module FranBehavior (
 franInit,runFranOnce,
 module FranBehavior,

 -- from module Event
 Event,Wire(..),neverE,
 mapE,filterE,mapMaybeE,withTimeE,afterTimeE,withIOE,
 traceE,mergeE,alarmE,arrayE,
 switcherL,
 addListenerE,newWire,addListener,
 (==>),(-=>),(.|.),anyE,withTimeE_,isJustE,suchThat,suchThat_,
 assocE,

 IfBehavior(..),
 module WorkPool,
 module FranTime,
 module BaseTypes,
 module Listener,
 module Behavior
 )
where
import Event (Event,Wire(..),neverE,
              mapE,filterE,mapMaybeE,withTimeE,afterTimeE,withIOE,
              traceE,mergeE,alarmE,arrayE,
              switcherL,
              addListenerE,newWire,addListener,
	      (==>),(-=>),(.|.),anyE,withTimeE_,isJustE,suchThat,suchThat_,
              assocE)
import qualified Event as E
import WorkPool
import FranTime
import BaseTypes
import Listener
import Behavior
import FranPrim (franInit,runFranOnce)
import qualified BehaviorIO as BIO
import qualified BPrim as B
import BehaviorIO (IfBehavior(..),joinB)
import Array
import IOExts

infixr 1 `switcher`, `untilB`

accumE :: a -> Event (a->a) -> Event a
accumE a e = unsafePerformIO $ E.accumE a e

distinctE :: Eq a => Event a -> Event a
distinctE e = unsafePerformIO $ E.distinctE e

distinctEWith :: (a -> a -> Bool) -> (a -> Bool) -> Event a -> Event a
distinctEWith cmp p e = unsafePerformIO $ E.distinctEWith cmp p e

accumIOE :: a -> Event (a -> IO a) -> Event a
accumIOE a e = unsafePerformIO $ E.accumIOE a e

switcherE :: Event a -> Event (Event a) -> Event a
switcherE e ee = unsafePerformIO $ E.switcherE e ee

manyE :: Event a -> Event (Event a) -> Event a
manyE e ee = unsafePerformIO $ E.manyE e ee

bindOneE :: Event a -> (a -> Event b) -> Event b
bindOneE e f = unsafePerformIO $ E.bindOneE e f

bindManyE :: Event a -> (a -> Event b) -> Event b
bindManyE e f = unsafePerformIO $ E.bindManyE e f

withElemE :: Event a -> [b] -> Event (a,b)
withElemE e bs = unsafePerformIO $ E.withElemE e bs

withElemE_ :: Event a -> [b] -> Event b
withElemE_ e bs = unsafePerformIO $ E.withElemE_ e bs

scanlE :: (a -> b -> a) -> a -> Event b -> Event a
scanlE f a e = unsafePerformIO $ E.scanlE f a e

withPrevE :: Event a -> a -> Event (a,a)
withPrevE e a = unsafePerformIO $ E.withPrevE e a

onceE :: Event a -> Event a
onceE e = unsafePerformIO $ E.onceE e

switcherB :: Behavior a -> Event (Behavior a) -> Behavior a
switcherB b e = unsafePerformIO $ B.switcherB b e

------ Generalized behaviors 


class Switchable bv where
 switcher      :: bv -> Event bv -> bv

untilB :: Switchable bv => bv -> Event bv ->  bv
b `untilB` e = b `switcher` onceE e

predicateB :: Behavior Bool -> Event ()
predicateB b = unsafePerformIO $ fmap (flip suchThat_ id) $ BIO.toStream b

instance Switchable (Event a) where
  switcher a e = switcherE a e

instance Switchable (Behavior a) where
  switcher a e = switcherB a e

accumB :: Switchable bv => (bv -> b -> bv) -> bv -> Event b -> bv 
accumB f soFar e = switcher soFar (scanlE f soFar e)

stepAccum :: a -> Event (a -> a) -> Behavior a 
stepAccum x0 change = unsafePerformIO $ B.stepAccum x0 change

stepper :: a -> Event a -> Behavior a
stepper a e = unsafePerformIO $ B.stepper a e

-- Count the number of event occurrences

countE :: Event a -> Behavior Int
countE e = stepAccum 0 (e -=> (+ 1))

