-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | JSON-RPC clients and servers using JMacro, and evented client-server Reactive Programming.
--   
--   Base jmacro-rpc package. Provides server-independent functions.
@package jmacro-rpc
@version 0.3.2


-- | The jmacro-rpc library provides an implementation of the JSON-RPC 2.0
--   protocol in Haskell (http:/<i>www.jsonrpc.org</i>), using typeclass
--   based induction to automatically wrap arbitrary Haskell functions up
--   as exposed RPCs, and to generate Haskell functions to call those RPCs
--   on a remote server. Facilities are also included to expose RPCs in
--   javascript on generated HTML pages, and to manage page-local (i.e.
--   "conversation") state on these pages. This package provides all core
--   functionality and APIs. Additional backend-specific packages are
--   provided for wiring these functions up to existing HTTP server
--   packages.
module Network.JMacroRPC.Base

-- | A JSON request is a list of values
type JRequest = [Value]

-- | A JSON result is either an error or a value.
type JResult = Either String Value

-- | A JsonRPC is a named function that takes a handle to some state, and
--   yields a function from request to result in some monad. It is a
--   representation of the server side of an RPC call.
data JsonRPC m s
JsonRPC :: String -> (s -> JRequest -> m JResult) -> JsonRPC m s

-- | retErr = return . Left
retErr :: Monad m => a -> m (Either a b)

-- | This class should not be used directly.
class Monad m => ToJsonRPC a m | a -> m
toJsonRPC_ :: ToJsonRPC a m => a -> ([Value] -> m JResult)

-- | Takes a compatible function to a JsonRPC.
toJsonRPC :: ToJsonRPC a m => String -> a -> JsonRPC m ()

-- | Takes a compatible function to a JsonRPC making use of state (i.e. a
--   conversation).
toJsonConvRPC :: ToJsonRPC a m => String -> (s -> a) -> JsonRPC m s

-- | This class should not be used directly.
class ToJsonRPCCall a b | a -> b
toJsonRPCCall_ :: ToJsonRPCCall a b => [Value] -> a -> b

-- | Send a function on Jsonable values to a function of the same signature
--   whose logic is invokable on a remote server. This function operates on
--   the type of its argument. The body can remain undefined.
toJsonRPCCall :: ToJsonRPCCall a b => a -> b

-- | Takes a name and a function and yields both the server-side JsonRPC
--   and the client-side stub.
mkJsonRPCPair :: (ToJsonRPC a m, ToJsonRPCCall a t) => String -> (s -> a) -> (t, JsonRPC m s)

-- | JMacro Javascript stub to invoke json-rpc calls from web browsers.
invokeRPCLib :: JStat

-- | id with a helpful type.
asIO :: IO a -> IO a

-- | Given a function for managing local state, and a list of JsonRPCs over
--   that local state, produce a function from Bytestring to Bytestring
--   mapping json-rpc requests to responses.
handleRpcs :: (Functor m, Monad m) => (Int -> m s) -> [JsonRPC m s] -> ByteString -> m ByteString

-- | Used for creating server backends. Yes, this type is confusing. But
--   unless you are creating a server backend, you can ignore it. Takes a
--   function to generate some time identifier, a function to cull page
--   state, a rpc handler, a function for creating a single page, a
--   function to initialize a page state, and a bunch of rpcs, and creates
--   a pair of handler functions (one for POST and one for GET) such that
--   individual clients first pull a page with an embedded ID, along with
--   client-side rpc functions. Those functions in turn interact with state
--   local to that invocation of a page when they make json-rpc requests to
--   the server. The cull function is in IO so it has access to whatever
--   notion of time it desires, including the opportunity to not run at
--   all. Note that the POST page should be served from the same url as the
--   get page, but with an additional "/jrpcs" directory guard.
mkConversationPageGen :: (MonadIO m1, MonadIO m) => IO timestamp -> (IntMap (timestamp, s) -> IO (IntMap (timestamp, s))) -> ((Int -> m s) -> [JsonRPC m s] -> m1 resp) -> (JStat -> m1 resp) -> IO s -> [JsonRPC m s] -> IO (m1 resp, m1 resp)

-- | Converts a json rpc to a javascript declaration of the appropriate
--   function.
jsonRPCToDecl :: JsonRPC a m -> JStat
type JState a = MVar (Either String a)
type JStateAsync a = MVar (Either (Int, String) (JState a))
instance Data.Aeson.Types.FromJSON.FromJSON b => Network.JMacroRPC.Base.ToJsonRPCCall (GHC.Types.IO (Data.Either.Either GHC.Base.String b)) ((Data.ByteString.Lazy.Internal.ByteString -> GHC.Types.IO (Data.Either.Either GHC.Base.String Data.ByteString.Lazy.Internal.ByteString)) -> Data.Aeson.Types.Internal.Value -> GHC.Base.String -> GHC.Types.IO (Data.Either.Either GHC.Base.String b))
instance (Data.Aeson.Types.ToJSON.ToJSON a, Network.JMacroRPC.Base.ToJsonRPCCall b c) => Network.JMacroRPC.Base.ToJsonRPCCall (a -> b) (a -> c)
instance Data.Aeson.Types.ToJSON.ToJSON b => Network.JMacroRPC.Base.ToJsonRPC (GHC.Types.IO (Data.Either.Either GHC.Base.String b)) GHC.Types.IO
instance (Data.Aeson.Types.FromJSON.FromJSON a, Network.JMacroRPC.Base.ToJsonRPC b m) => Network.JMacroRPC.Base.ToJsonRPC (a -> b) m


-- | The Panels library provides continuation-style compositional web
--   development with no scaling hassle. On the server side, Panels are
--   entirely stateless, storing no client-specific state. This also means
--   that requests can be sharded to multiple servers without worrying
--   about replication of large session objects (authentication choices are
--   another issue entirely).
--   
--   Code is written with a set of combinators over <a>Panel</a>s, which
--   package up display and behavior simultaneously. Panels, inspired by
--   FRP, can provide <a>Signal</a>s, which are sampleable, <a>Event</a>s,
--   which are discrete and can trigger updates, and <a>Sink</a>s which can
--   be bound to Signals (behaving similarly to FRP wormholes). Semantics,
--   by virtue of client-server interaction, are necessarily evented rather
--   than continuous.
--   
--   Panels, which are built using this library, can then be displayed
--   using one of a number of servers as backends. New backends can be
--   created with the <a>panelToPageGen</a> function.
--   
--   Example usage:
--   
--   <pre>
--   testPanel :: (Monad m, Functor m) =&gt; Panel m
--   testPanel =    para "This is an example"
--             &lt;&gt; plainHTML Blaze.br
--             &lt;&gt; inDiv [
--                     select ("default",1::Int) [("another",2)] $ \ evt selSignal selPanel -&gt;
--                     selPanel &lt;&gt;
--                      (onEvent evt $
--                       withSample selSignal $ \ selChoice -&gt;
--                       select (show selChoice, selChoice)
--                           [(show $ selChoice + 1, selChoice + 1)] $ \ _evt selSignal2 selPanel2 -&gt;
--                       button "click me" $ \ buttonEvt buttonPanel -&gt;
--                       onEvent buttonEvt $
--                       withSample selSignal2 $ \ selChoice2 -&gt;
--                       (selPanel2 &lt;&gt; buttonPanel &lt;&gt; plainHTML Blaze.br
--                        &lt;&gt; (para $ "you chose: " ++ show (selChoice, selChoice2))))
--                ]
--   </pre>
--   
--   The above code displays two dropdown menus and a button. The first
--   dropdown determines the contents of the second. On clicking the
--   button, the text updates with choices from both the first and second
--   dropdowns.
--   
--   See the source of <a>calcPanel</a> for an example of mixed
--   client/server updates with more complicated stateful interaction.
module Network.JMacroRPC.Panels

-- | Type tag for Sinks and Signals that can be run in pure JavaScript.
data JS

-- | Type tag for Sinks and Signals that require server-side interaction.
data Hask

-- | Unique label for any given panel in a control structure.
type PanelPath = [Int]

-- | Conceptually, an Event is something that can trigger an update. We can
--   join two events (which gives us "or" semantics), and we can trigger on
--   an event. That's it. In reality, an event is composed of the
--   panelpaths to it's sources.
data Event
Event :: [PanelPath] -> Event

-- | A Signal can contain information drawn from client-side inputs.
--   Signals are tagged as JS, Hask, or parametric. A signal of type JS can
--   be read from purely on the client side, with no round trip. A signal
--   of type Hask forms an applicative functor, so we can build server-side
--   values with complex computed behaviours. Note that <tt>Signal
--   Hask</tt> actually bends the applicative functor laws in that <tt>fmap
--   id</tt> on a signal that can be calculated directly in JS can send it
--   to a signal that cannot be. This is a flaw, and it will be fixed.
data Signal typ a
[PureSig] :: a -> Signal typ a
[OneSig] :: FromJSON a => PanelPath -> Signal typ a
[MultiSig] :: Signal typ1 a -> Signal typ2 b -> ((a, b) -> c) -> Signal Hask c

-- | Sinks likewise are tagged as JS, Hask, or parametric. A sink of type
--   JS can be written to purely on the client side, with no round trip. A
--   sink of type Hask is a contravariant functor.
data Sink typ m a
[ServerSink] :: (a -> PState m [JStat]) -> Sink Hask m a
[PureSink] :: ToJExpr a => JExpr -> Sink typ m a

-- | A PanelState contains environment information used to render Panels.
data PanelState
PanelState :: PanelPath -> Map String ByteString -> Map String ByteString -> Set String -> Maybe (String, Map String ByteString) -> PanelState
[ps_path] :: PanelState -> PanelPath
[ps_env] :: PanelState -> Map String ByteString
[ps_env_clean] :: PanelState -> Map String ByteString
[ps_events] :: PanelState -> Set String
[ps_listener] :: PanelState -> Maybe (String, Map String ByteString)

-- | The PState Monad Transformer provides access o the PanelState.
type PState m a = StateT PanelState m a

-- | We can get a fresh identifier out of a panel state.
newIdent :: (Monad m, Functor m) => PState m PanelPath

-- | And we can get an identifier out before descending into a "local"
--   environment whose identifiers don't affect the main supply. Hence if a
--   local environment alters its pattern of consumption, identifiers in
--   the outer environment will remain stable.
descended :: (Monad m, Functor m) => (PanelPath -> PState m a) -> PState m a

-- | A PageSlice is a pair of Html and JavaScript. When a Panel is
--   rendered, all JavaScript ends up joined together in the head of the
--   page, and all HTML below it. PageSlices are naturally Monoidal, just
--   as Html is.
data PageSlice
PS :: Html -> [JStat] -> PageSlice
[htmlP] :: PageSlice -> Html
[jsP] :: PageSlice -> [JStat]

-- | A Panel is the pair of an action to produce a PageSlice and an action
--   to produce a list of locations with updated PageSlices. The former is
--   used to draw the initial page, and the latter to modify it in response
--   to events. Panels are also naturally Monoidal.
data Panel m
Panel :: PState m PageSlice -> PState m [(PanelPath, PageSlice)] -> Panel m
[drawP] :: Panel m -> PState m PageSlice
[updateP] :: Panel m -> PState m [(PanelPath, PageSlice)]
type UpdateList = [(String, (String, String))]

-- | Since only some Signals are applicative functors, pureSig provides a
--   <tt>pure</tt> operation over all Signals.
pureSig :: a -> Signal typ a

-- | We can zip sinks up to combine them.
zipSinks :: Monad m => Sink Hask m a -> Sink Hask m b -> Sink Hask m (a, b)

-- | A JavaScript funcion can be contravariantly mapped over a Sink JS
contramapJs :: ToJExpr a => JExpr -> Sink JS m b -> Sink JS m a

-- | We can lift any Html into a Panel trivially.
plainHTML :: (Monad m, Functor m) => Html -> Panel m

-- | Similarly, we can map over any Html inside a panel (although the
--   behavior may be odd on panels with internal update semantics).
onHtml :: (Monad m, Functor m) => (Html -> Html) -> Panel m -> Panel m

-- | Given a function to join Html sections, we can fuse a list of panels
--   into a single pannel by lifting that function.
joinWith :: (Monad m, Functor m) => ([Html] -> Html) -> [Panel m] -> Panel m

-- | This is a general purpose function for constructing Panels that
--   provide signals and events, and optionally sinks. It takes a function
--   from an identifier path to an intial value of a signal, optional sinks
--   into the signal, and a panel "controlling" the signal. From this it
--   yields a continuation function from the event and signal associated
--   wih the panel, the optional sinks, and the signal "control" panel to a
--   new panel to the new panel iself. Usage of this function is best
--   understood by viewing the source of inputs built using it.
buildInput :: (FromJSON a, ToJSON a, Monad m, Functor m) => (PanelPath -> (a, sinks, Panel m)) -> (Event -> Signal typ a -> sinks -> Panel m -> Panel m) -> Panel m

-- | Put a bunch of panels into a single div element. <tt>inDiv = onHtml
--   H.div . mconcat</tt>
inDiv :: (Monad m, Functor m) => [Panel m] -> Panel m

-- | Put some text into a p element. <tt>para = plainHTML . H.p .
--   fromString</tt>
para :: (Monad m, Functor m) => String -> Panel m

-- | Align a list of panels into a table with rows of the specified width.
--   <tt>mkTable n xs = onHtml H.table . mconcat . map row $ chunksOf n xs
--   where row ys = onHtml H.tr . mconcat $ map (onHtml H.td) ys</tt>
mkTable :: (Monad m, Functor m) => Int -> [Panel m] -> Panel m

-- | Given an arbitrary Signal, and a continuation accepting a value of the
--   underlying type of the signal, yield a simple Panel.
withSample :: (FromJSON a, Monad m, Functor m) => Signal typ a -> (a -> Panel m) -> Panel m

-- | Given a Signal JS, produce a JavaScript expression that samples the
--   value of the signal.
sampleSigJs :: ToJSON a => Signal JS a -> JExpr

-- | Given an Event, and a Panel, update the Panel each time the event
--   fires.
onEvent :: (Monad m, Functor m) => Event -> Panel m -> Panel m

-- | Feed a value to a Sink.
tellSink :: (Functor m, Monad m) => Sink typ m a -> a -> Panel m

-- | Given an event, a signal, and a sink, on each firing of the event,
--   feed the sink the current sampled value of the signal. If the Signal
--   and Sink are both in JS, this can happen entirely on the client side.
bindSigSink :: (Monad m, Functor m, FromJSON a, ToJSON a) => Event -> Signal typ1 a -> Sink typ2 m a -> Panel m

-- | Perform an action in the underlying monad and feed the result to a
--   panel. Synchronous. Note that this action will occur on every update,
--   even when guarded by an onEvent.
sampleIO :: (Monad m) => m a -> (a -> Panel m) -> Panel m

-- | Execute an IO action when triggered by an event. This action only
--   occurs when the event fires. <tt>bindEventIO e act = onEvent e $ Panel
--   (return mempty) (lift act &gt;&gt; return mempty)</tt>
bindEventIO :: (Monad m, Functor m) => Event -> m () -> Panel m

-- | Takes an initial value and a continuation taking an event and the
--   button itself, yields a panel.
button :: (Monad m, Functor m) => String -> (Event -> Panel m -> Panel m) -> Panel m

-- | Takes an intial (label, value) pair, a list of pairs of labeled
--   values, and a continuation, building a Panel with a dropdown selector.
select :: (Monad m, Functor m, ToJSON a, FromJSON a) => (String, a) -> [(String, a)] -> (Event -> Signal typ a -> Panel m -> Panel m) -> Panel m

-- | a wrapper around select that immediately samples from the yielded
--   signal. <tt>selectInput defOpt opts k = select defOpt opts $ e sig p
--   -&gt; withSample sig $ i -&gt; k e i p</tt>
selectInput :: (Monad m, Functor m, FromJSON a, ToJSON a) => (String, a) -> [(String, a)] -> (Event -> a -> Panel m -> Panel m) -> Panel m

-- | A basic text input box. This box provides a Sink as well as a Signal,
--   so it's contents can be controlled from elsewhere in the Panel.
textPane :: (Monad m, Functor m) => String -> (Event -> Signal typ String -> Sink typ m String -> Panel m -> Panel m) -> Panel m

-- | A hidden input Panel that can be used as a mutable store, akin to an
--   IORef or MVar.
newVar :: (Monad m, Functor m, ToJSON a, FromJSON a, ToJExpr a) => a -> (Event -> Signal typ a -> Sink typ m a -> Panel m -> Panel m) -> Panel m

-- | JavaScript code for the reactive runtime system.
panelPrelude :: JStat

-- | General function used to create backends for different servers and
--   frameworks.
panelToPageGen :: forall m resp. (Monad m, Functor m, ToJsonRPC (m (Either String UpdateList)) m) => ([JsonRPC m ()] -> m resp) -> (Text -> m resp) -> Maybe String -> String -> Panel m -> (m resp, m resp)

-- | Example panel that displays a calculator.
calcPanel :: (Monad m, Functor m) => Panel m
instance GHC.Show.Show Network.JMacroRPC.Panels.PanelState
instance GHC.Base.Monad m => GHC.Base.Monoid (Network.JMacroRPC.Panels.Panel m)
instance GHC.Base.Monoid Network.JMacroRPC.Panels.PageSlice
instance GHC.Base.Monad m => Data.Functor.Contravariant.Contravariant (Network.JMacroRPC.Panels.Sink Network.JMacroRPC.Panels.Hask m)
instance GHC.Base.Functor (Network.JMacroRPC.Panels.Signal Network.JMacroRPC.Panels.Hask)
instance GHC.Base.Applicative (Network.JMacroRPC.Panels.Signal Network.JMacroRPC.Panels.Hask)
instance GHC.Base.Monoid Network.JMacroRPC.Panels.Event
