\begin{code}
module FRPWrap (
 module FRPWrap,
 module Listener,
 module Behavior,
 module FranTime,
 module BaseTypes,
 module Remover,

 Event,Wire(..),
 neverE,
 mapE,filterE,mapMaybeE,withTimeE,afterTimeE,mapEs,fromListE,
 traceE,mergeE,arrayE,alarmE,
 onceE,scanlE,distinctEWith,accumE,accumIOE,withElemE,switcherE,manyE,
 switcherL,
 (==>),(-=>),(.|.),anyE,withTimeE_,isJustE,suchThat_,assocE,

 SwitchableM(..),IfBehavior(..),

 bindOneE,bindManyE,withPrevE,withPrevE_,withElemE_,
 withElemE_,manyE,switcherE,withElemE,accumE,
 distinctEWith,distinctE,scanlE,onceE,
 addListener,
 predicateB,countE,
 switcherB,stepper,stepAccum


 
 ) where
import FranCore hiding (bindOneE,bindManyE,withPrevE,withPrevE_,withElemE_,
			withElemE_,manyE,switcherE,withElemE,accumE,
			distinctEWith,distinctE,scanlE,onceE,predicateB,
			countE,switcherB,stepper,stepAccum,addListener)
import qualified FranCore as E
import GUI
import GUIDef
import MapG
import BVars
import Listener
import Behavior
import Remover
import BaseTypes
import FranTime
\end{code}

lifted GUI monad operations for creating various bvars and wires

\begin{code}
mkBVar :: a -> GUI (BVar a)
mkBVar a = liftIO $ newBVar a

mkBVarE :: a -> Event (a -> a) -> GUI (BVar a)
mkBVarE a e = liftIO $ newBVarE a e

mkWire :: GUI (Wire a)
mkWire = liftIO $ newWire

mkCollectionB :: CollectionOp a b => Event (a c) -> b c 
               -> GUI (CollectionB a b c)
mkCollectionB e c = liftIO $ newCollectionB e c

mkSetB :: Set a -> Event (SetOp a) -> GUI (SetB a)
mkSetB e c = liftIO $ newSetB e c

mkListB :: List a -> Event (ListOp a) -> GUI (ListB a)
mkListB e c = liftIO $ newListB e c

mkSetBVar :: (Eq a) => [a] -> GUI (SetBVar a)
mkSetBVar c = liftIO $ newSetBVar c

mkListBVar :: (Eq a) => [a] -> GUI (ListBVar a)
mkListBVar c = liftIO $ newListBVar c

mkSetBVar' :: (a -> Ident) -> [a] -> GUI (SetBVar a)
mkSetBVar' identify c = liftIO $ newSetBVar' identify c

mkListBVar' :: (a -> Ident) -> [a] -> GUI (ListBVar a)
mkListBVar' identify c = liftIO $ newListBVar' identify c
\end{code}

gui actions and listeners. as listeners only deal with IO actions
we need to pass in the GUIDef state. Note that this means GUI listeners
are always evaluating their actions in the context of where they were
created. This only really affects create widget commands. These should
be ok as we always pass around components which are the GUI actions themselves
and then run them only when displaying the widget.

\begin{code}
mkGUIL :: (a -> GUI ()) -> GUI (Listener a)
mkGUIL f = withGUIDef $ \d -> return $ mkL $ runGUI d . f

comapGUIL :: (a -> GUI b) -> Listener b -> GUI (Listener a)
comapGUIL f l = withGUIDef $ \d -> return $ comapIOL (runGUI d . f) l


comapMaybeGUIL :: (a -> GUI (Maybe b)) -> Listener b -> GUI (Listener a)
comapMaybeGUIL f l = withGUIDef $ \d -> return $ comapMaybeIOL (runGUI d . f) l

mapGUIL = comapGUIL
mapMaybeGUIL = comapMaybeGUIL

mkGUIL_ :: GUI () -> GUI (Listener a)
mkGUIL_ f = mkGUIL $ const f

mapGUIL_ :: GUI b -> Listener b -> GUI (Listener a)
mapGUIL_ f l = mapGUIL (const f) l
\end{code}

mapping GUI valued functions over collections and events.
and GUI switchers.

\begin{code}

instance MapG Event a b GUI where
  mapG f e = do
   info <- getGUIDef
   return $! withIOE e (\x -> runGUI info (f x))   

instance (MapG e a b IO,MapG c a b IO,CollectionOp e c) =>
         MapG (CollectionB e c) a b GUI where
 mapG f coll = do
  info <- getGUIDef 
  liftIO $ mapG (\v -> runGUI info $ f v) coll

instance SwitchableM (Event a) GUI where
 mkSwitcher e ee = liftIO $ mkSwitcher e ee

instance SwitchableM (Behavior a) GUI where
 mkSwitcher e ee = liftIO $ mkSwitcher e ee

instance CollectionOp b c => SwitchableM (CollectionB b c a) GUI where
 mkSwitcher e ee = liftIO $ mkSwitcher e ee

\end{code}

Lift all IO related stuff to GUI functions

\begin{code}

onceE :: Event a -> GUI (Event a)
onceE e = liftIO $ E.onceE e

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

distinctEWith :: (a -> a -> Bool) -> (a -> Bool) -> Event a -> GUI (Event a)
distinctEWith p f e = liftIO $ E.distinctEWith p f e

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

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

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

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

-- filter out duplicate occurrences
distinctE :: Eq a => Event a -> GUI (Event a)
distinctE = distinctEWith (==) (const False)

-- associate list with event occurrences
withElemE_ :: Event a -> [b] -> GUI (Event b)
e `withElemE_` l = fmap (mapE snd) $ e `withElemE` l 

-- get only previous occurrences

withPrevE :: Event a -> a -> GUI (Event (a,a))
e `withPrevE` a0 = scanlE (\(older,old) new -> (old,new))
                          (error "withPrevE: no prev", a0)
                          e

withPrevE_ :: Event a -> a -> GUI (Event a)
e `withPrevE_` a0 = fmap (mapE snd) $ e `withPrevE` a0 


bindOneE :: Event a -> (a -> Event b) -> GUI (Event b)
bindOneE ev f = neverE `switcherE` mapE f ev

bindManyE :: Event a -> (a -> Event b) -> GUI (Event b)
bindManyE ev f = neverE `manyE` mapE f ev

addListener :: Event a -> Listener a -> GUI (GUI ())
addListener e l = fmap liftIO $ liftIO $ E.addListener e l
\end{code}

\begin{code}
predicateB :: Behavior Bool -> GUI (Event ())
predicateB b = liftIO $ E.predicateB b

countE :: Event a -> GUI (Behavior Int)
countE e = liftIO $ E.countE e

switcherB :: Behavior a -> Event (Behavior a) -> GUI (Behavior a)
switcherB b e = liftIO $ E.switcherB b e

stepper :: a -> Event a -> GUI (Behavior a)
stepper b e = liftIO $ E.stepper b e

stepAccum :: a -> Event (a -> a) -> GUI (Behavior a)
stepAccum a e = liftIO $ E.stepAccum a e

\end{code}
