module Web.Hyperbole.Effect.Respond where

import Data.Text (Text)
import Effectful
import Effectful.Dispatch.Dynamic
import Web.Hyperbole.Effect.Hyperbole (Hyperbole (..))
import Web.Hyperbole.Effect.Server (Response (..), ResponseError (..), TargetViewId (..))
import Web.Hyperbole.HyperView (HyperView (..), ViewId (..), hyperUnsafe)
import Web.View (Url, View)


-- | Respond with the given view, and stop execution
respondEarly :: (Hyperbole :> es, HyperView id es) => id -> View id () -> Eff es ()
respondEarly :: forall (es :: [Effect]) id.
(Hyperbole :> es, HyperView id es) =>
id -> View id () -> Eff es ()
respondEarly id
i View id ()
vw = do
  let vid :: TargetViewId
vid = Text -> TargetViewId
TargetViewId (id -> Text
forall a. ViewId a => a -> Text
toViewId id
i)
  let res :: Response
res = TargetViewId -> View () () -> Response
Response TargetViewId
vid (View () () -> Response) -> View () () -> Response
forall a b. (a -> b) -> a -> b
$ id -> View id () -> View () ()
forall id ctx. ViewId id => id -> View id () -> View ctx ()
hyperUnsafe id
i View id ()
vw
  Hyperbole (Eff es) () -> Eff es ()
forall (e :: Effect) (es :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (Hyperbole (Eff es) () -> Eff es ())
-> Hyperbole (Eff es) () -> Eff es ()
forall a b. (a -> b) -> a -> b
$ Response -> Hyperbole (Eff es) ()
forall (a :: * -> *) b. Response -> Hyperbole a b
RespondEarly Response
res


{- | Respond immediately with 404 Not Found

@
userLoad :: (Hyperbole :> es, Users :> es) => UserId -> Eff es User
userLoad uid = do
  mu <- send (LoadUser uid)
  maybe notFound pure mu

myPage :: (Hyperbole :> es, Users :> es) => Eff es View
myPage = do
  load $ do
    u <- userLoad 100
    -- skipped if user = Nothing
    pure $ userView u
@
-}
notFound :: (Hyperbole :> es) => Eff es a
notFound :: forall (es :: [Effect]) a. (Hyperbole :> es) => Eff es a
notFound = Hyperbole (Eff es) a -> Eff es a
forall (e :: Effect) (es :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (Hyperbole (Eff es) a -> Eff es a)
-> Hyperbole (Eff es) a -> Eff es a
forall a b. (a -> b) -> a -> b
$ Response -> Hyperbole (Eff es) a
forall (a :: * -> *) b. Response -> Hyperbole a b
RespondEarly Response
NotFound


-- | Respond immediately with a parse error
parseError :: (Hyperbole :> es) => Text -> Eff es a
parseError :: forall (es :: [Effect]) a. (Hyperbole :> es) => Text -> Eff es a
parseError = Hyperbole (Eff es) a -> Eff es a
forall (e :: Effect) (es :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (Hyperbole (Eff es) a -> Eff es a)
-> (Text -> Hyperbole (Eff es) a) -> Text -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Response -> Hyperbole (Eff es) a
forall (a :: * -> *) b. Response -> Hyperbole a b
RespondEarly (Response -> Hyperbole (Eff es) a)
-> (Text -> Response) -> Text -> Hyperbole (Eff es) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ResponseError -> Response
Err (ResponseError -> Response)
-> (Text -> ResponseError) -> Text -> Response
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ResponseError
ErrParse


-- | Redirect immediately to the 'Url'
redirect :: (Hyperbole :> es) => Url -> Eff es a
redirect :: forall (es :: [Effect]) a. (Hyperbole :> es) => Url -> Eff es a
redirect = Hyperbole (Eff es) a -> Eff es a
forall (e :: Effect) (es :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (Hyperbole (Eff es) a -> Eff es a)
-> (Url -> Hyperbole (Eff es) a) -> Url -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Response -> Hyperbole (Eff es) a
forall (a :: * -> *) b. Response -> Hyperbole a b
RespondEarly (Response -> Hyperbole (Eff es) a)
-> (Url -> Response) -> Url -> Hyperbole (Eff es) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Url -> Response
Redirect


-- | Manually set the response to the given view. Normally you return a 'View' from 'load' or 'handle' instead of using this
view :: (Hyperbole :> es) => View () () -> Eff es Response
view :: forall (es :: [Effect]).
(Hyperbole :> es) =>
View () () -> Eff es Response
view View () ()
vw = do
  Response -> Eff es Response
forall a. a -> Eff es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Response -> Eff es Response) -> Response -> Eff es Response
forall a b. (a -> b) -> a -> b
$ TargetViewId -> View () () -> Response
Response (Text -> TargetViewId
TargetViewId Text
"") View () ()
vw