-- | Functions and types used to describe the `HalogenF` algebra used in a
-- | component's `eval` function.
module Halogen.Query
  ( Tell
  , mkTell
  , tell
  , tellAll
  , Request
  , mkRequest
  , request
  , requestAll
  , getHTMLElementRef
  , module Halogen.Query.Input
  , module Halogen.Query.HalogenM
  , module Halogen.Query.HalogenQ
  )
where

import Data.Row as Row
import HPrelude
import Halogen.Data.Slot (Slot)
import Halogen.Query.HalogenM (ForkId, HalogenF (..), HalogenM (..), SubscriptionId, fork, getRef, join, kill, query, queryAll, raise, subscribe, subscribe', unsubscribe)
import Halogen.Query.HalogenQ (HalogenQ (..))
import Halogen.Query.Input (RefLabel (..))
import Web.DOM.Internal.Types

-- | Type synonym for a "tell-style" query - queries that only cause effects,
-- | but that cannot receive a return value.
-- |
-- | In a query algebra, a tell constructor carries the algebra's type variable
-- | as its last argument. For example:
-- |
-- | ``` purescript
-- | data Query a
-- |   = SomeTell a
-- |   | SomeOtherTell String a
-- |   | NotATell (Boolean -> a)
-- | ```
-- |
-- | Both `SomeTell` and `SomeOtherTell` carry a plain `a` as a value, whereas
-- | `NotATell` has `a` as the result of a function so is considered to be a
-- | "request" ([see below](#Request)).
type Tell f = () -> f ()

-- | Takes a data constructor of query algebra `f` and creates a tell query.
-- |
-- | For example:
-- |
-- | ```purescript
-- | data Query a = Tick a
-- |
-- | sendTick :: forall o. H.HalogenSocket Query o IO -> IO (Maybe ())
-- | sendTick app = app.query (H.mkTell Tick)
-- | ```
mkTell :: forall f. Tell f -> f ()
mkTell :: forall (f :: * -> *). Tell f -> f ()
mkTell Tell f
act = Tell f
act ()

tell
  :: forall label
    ->forall state action output m slots query output' slot
   . (HasType label (Slot query output' slot) slots, Functor m)
  => (KnownSymbol label)
  => (Ord slot)
  => slot
  -> Tell query
  -> HalogenM state action slots output m ()
tell :: forall (label :: Symbol) ->
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot.
(HasType label (Slot query output' slot) slots, Functor m,
 KnownSymbol label, Ord slot) =>
slot -> Tell query -> HalogenM state action slots output m ()
tell label slot
slot Tell query
req = HalogenM state action slots output m (Maybe ())
-> HalogenM state action slots output m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (HalogenM state action slots output m (Maybe ())
 -> HalogenM state action slots output m ())
-> HalogenM state action slots output m (Maybe ())
-> HalogenM state action slots output m ()
forall a b. (a -> b) -> a -> b
$ slot -> query () -> HalogenM state action slots output m (Maybe ())
forall (label :: Symbol) ->
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot a.
(HasType label (Slot query output' slot) slots, KnownSymbol label,
 Ord slot, Functor m) =>
slot -> query a -> HalogenM state action slots output m (Maybe a)
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot a.
(HasType label (Slot query output' slot) slots, KnownSymbol label,
 Ord slot, Functor m) =>
slot -> query a -> HalogenM state action slots output m (Maybe a)
query label slot
slot (Tell query
req ())

tellAll
  :: forall label
    ->forall state action output m slots query output' slot
   . (HasType label (Slot query output' slot) slots, Functor m)
  => (KnownSymbol label)
  => (Ord slot)
  => Tell query
  -> HalogenM state action slots output m ()
tellAll :: forall (label :: Symbol) ->
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot.
(HasType label (Slot query output' slot) slots, Functor m,
 KnownSymbol label, Ord slot) =>
Tell query -> HalogenM state action slots output m ()
tellAll label Tell query
req = HalogenM state action slots output m (Map slot ())
-> HalogenM state action slots output m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (HalogenM state action slots output m (Map slot ())
 -> HalogenM state action slots output m ())
-> HalogenM state action slots output m (Map slot ())
-> HalogenM state action slots output m ()
forall a b. (a -> b) -> a -> b
$ query () -> HalogenM state action slots output m (Map slot ())
forall (label :: Symbol) ->
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot a.
(HasType label (Slot query output' slot) slots, KnownSymbol label,
 Ord slot, Functor m) =>
query a -> HalogenM state action slots output m (Map slot a)
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot a.
(HasType label (Slot query output' slot) slots, KnownSymbol label,
 Ord slot, Functor m) =>
query a -> HalogenM state action slots output m (Map slot a)
queryAll label (Tell query
req ())

-- | Type synonym for an "request-style" query - queries that can cause effects
-- | as well as fetching some information from a component.
-- |
-- | In a query algebra, a request constructor carries the algebra's type
-- | variable as the return value of a function as its last argument. For
-- | example:
-- |
-- | ``` purescript
-- | data Query a = SomeRequest (Boolean -> a)
-- | ```
type Request f a = (a -> a) -> f a

-- | Takes a data constructor of query algebra `f` and creates a request query.
-- |
-- | For example:
-- |
-- | ```purescript
-- | data Query a = GetTickCount (Int -> a)
-- |
-- | getTickCount :: forall o. H.HalogenSocket Query o IO -> IO (Maybe Int)
-- | getTickCount app = app.query (H.mkRequest GetTickCount)
-- | ```
mkRequest :: forall f a. Request f a -> f a
mkRequest :: forall (f :: * -> *) a. Request f a -> f a
mkRequest Request f a
req = Request f a
req a -> a
forall a. a -> a
identity

request
  :: forall label
    ->forall state action output m slots query output' slot a
   . (HasType label (Slot query output' slot) slots, Functor m)
  => (KnownSymbol label)
  => (Ord slot)
  => slot
  -> Request query a
  -> HalogenM state action slots output m (Maybe a)
request :: forall (label :: Symbol) ->
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot a.
(HasType label (Slot query output' slot) slots, Functor m,
 KnownSymbol label, Ord slot) =>
slot
-> Request query a
-> HalogenM state action slots output m (Maybe a)
request slot slot
label Request query a
req = slot -> query a -> HalogenM state action slots output m (Maybe a)
forall (label :: Symbol) ->
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot a.
(HasType label (Slot query output' slot) slots, KnownSymbol label,
 Ord slot, Functor m) =>
slot -> query a -> HalogenM state action slots output m (Maybe a)
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot a.
(HasType label (Slot query output' slot) slots, KnownSymbol label,
 Ord slot, Functor m) =>
slot -> query a -> HalogenM state action slots output m (Maybe a)
query slot slot
label (Request query a
req a -> a
forall a. a -> a
identity)

requestAll
  :: forall label
    ->forall state action output m slots query output' slot a
   . (HasType label (Slot query output' slot) slots, Functor m)
  => (KnownSymbol label)
  => (Ord slot)
  => Request query a
  -> HalogenM state action slots output m (Map slot a)
requestAll :: forall (label :: Symbol) ->
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot a.
(HasType label (Slot query output' slot) slots, Functor m,
 KnownSymbol label, Ord slot) =>
Request query a
-> HalogenM state action slots output m (Map slot a)
requestAll label Request query a
req = query a -> HalogenM state action slots output m (Map slot a)
forall (label :: Symbol) ->
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot a.
(HasType label (Slot query output' slot) slots, KnownSymbol label,
 Ord slot, Functor m) =>
query a -> HalogenM state action slots output m (Map slot a)
forall state action output (m :: * -> *) (slots :: Row (*))
       (query :: * -> *) output' slot a.
(HasType label (Slot query output' slot) slots, KnownSymbol label,
 Ord slot, Functor m) =>
query a -> HalogenM state action slots output m (Map slot a)
queryAll label (Request query a
req a -> a
forall a. a -> a
identity)

-- | Retrieves a `HTMLElement` value that is associated with a `Ref` in the
-- | rendered output of a component. If there is no currently rendered value (or
-- | it is not an `HTMLElement`) for the request will return `Nothing`.
getHTMLElementRef
  :: forall state action slots output m
   . (Functor m)
  => RefLabel
  -> HalogenM state action slots output m (Maybe HTMLElement)
getHTMLElementRef :: forall state action (slots :: Row (*)) output (m :: * -> *).
Functor m =>
RefLabel
-> HalogenM state action slots output m (Maybe HTMLElement)
getHTMLElementRef = (Maybe Element -> Maybe HTMLElement)
-> HalogenM state action slots output m (Maybe Element)
-> HalogenM state action slots output m (Maybe HTMLElement)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (Element -> Maybe HTMLElement
fromElement (Element -> Maybe HTMLElement)
-> Maybe Element -> Maybe HTMLElement
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<) (HalogenM state action slots output m (Maybe Element)
 -> HalogenM state action slots output m (Maybe HTMLElement))
-> (RefLabel
    -> HalogenM state action slots output m (Maybe Element))
-> RefLabel
-> HalogenM state action slots output m (Maybe HTMLElement)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RefLabel -> HalogenM state action slots output m (Maybe Element)
forall state action (slots :: Row (*)) output (m :: * -> *).
Functor m =>
RefLabel -> HalogenM state action slots output m (Maybe Element)
getRef