module Web.Hyperbole.Page where

import Data.Kind (Type)
import Effectful
import Web.Hyperbole.Effect.Handler (RunHandlers, runLoad)
import Web.Hyperbole.Effect.Hyperbole
import Web.Hyperbole.Effect.Server (Response)
import Web.Hyperbole.HyperView (Root)
import Web.View (View)


{- | Conceptually, an application is dividied up into multiple [Pages](#g:pages). Each page module should have a function that returns a 'Page'. The 'Page' itself is a 'View' with a type-level list of 'HyperView's used on the page.

@
page :: 'Eff' es ('Page' [Message, Count])
page = do
  pure $ do
    row id $ do
      'hyper' Message $ messageView \"Hello\"
      'hyper' Count $ countView 0
@
-}
type Page (views :: [Type]) = View (Root views) ()


{- | Run a 'Page' and return a 'Response'

@
main :: IO ()
main = do
  'run' 3000 $ do
    'liveApp' ('basicDocument' \"Example\") ('runPage' page)

page :: 'Eff' es ('Page' '[])
page = do
  pure $ do
    col (pad 10) $ do
      'el' bold \"Hello World\"
@
-}
runPage
  :: (Hyperbole :> es, RunHandlers views es)
  => Eff es (Page views)
  -> Eff es Response
runPage :: forall (es :: [Effect]) (views :: [*]).
(Hyperbole :> es, RunHandlers views es) =>
Eff es (Page views) -> Eff es Response
runPage = Eff es (View (Root views) ()) -> Eff es Response
forall (views :: [*]) (es :: [Effect]).
(Hyperbole :> es, RunHandlers views es) =>
Eff es (View (Root views) ()) -> Eff es Response
runLoad