{-# LANGUAGE NoRebindableSyntax #-}
{-# OPTIONS_GHC -Wno-type-defaults #-}

module Literate.Web.Live.HTTP where

-- import Network.Wai.Middleware.Static qualified as Static
import Control.Concurrent.STM (STM)
import Control.Concurrent.STM qualified as STM
import Control.Monad.Classes qualified as MC
import Data.ByteString.Lazy qualified as BSL
import Data.Function (($))
import Data.Map.Strict qualified as Map
import Data.Maybe (Maybe (..), fromMaybe)
import Data.Semigroup (Semigroup (..))
import Data.Text qualified as Text
import Data.Text.Lazy qualified as TextL
import Data.Text.Lazy.IO qualified as TextL
import Literate.Web qualified as Web
import Network.HTTP.Types qualified as H
import Network.Wai qualified as Wai
import System.IO (IO)
import System.IO qualified as Sys

import Literate.Web.Live.Asset
import Literate.Web.Live.Common

httpApp ::
  m ~ IO =>
  STM model ->
  (model -> m (Map.Map Web.OutputPath (m BSL.ByteString))) ->
  -- The shim to include in every HTML response
  Maybe BSL.ByteString ->
  Wai.Application
httpApp modelSTM siteMap mShim req res = do
  let shim = fromMaybe "" mShim
  let path = Text.intercalate "/" $ Wai.pathInfo req
  model <- STM.atomically modelSTM
  TextL.hPutStrLn Sys.stderr $ "httpApp: GET " <> TextL.fromStrict path
  site <- siteMap model
  Sys.hPrint
    Sys.stderr
    ( ["httpApp"] :: [TextL.Text]
    , ("path", decodeOutputPath path)
    , ("site" :: TextL.Text, (Map.keys site))
    )
  case Map.lookup (decodeOutputPath path) site of
    Nothing -> do
      let s = liveErrorHtmlResponse decodeRouteNothingMsg <> shim
      res $ Wai.responseLBS H.status404 [(H.hContentType, "text/html")] s
    Just contentIO -> do
      content <- MC.exec @IO contentIO
      res $ Wai.responseLBS H.status200 [(H.hContentType, "text/html")] content

{-
case mr of
  Left err -> do
    logErrorNS "App" $ badRouteEncodingMsg err
    let s = liveErrorHtmlResponse (badRouteEncodingMsg err) <> shim
    liftIO $ res $ Wai.responseLBS H.status500 [(H.hContentType, "text/html")] s
  Right Nothing -> do
    let s = liveErrorHtmlResponse decodeRouteNothingMsg <> shim
    liftIO $ res $ Wai.responseLBS H.status404 [(H.hContentType, "text/html")] s
  Right (Just r) -> do
    renderCatchingErrors val r >>= \case
      AssetStatic staticPath -> do
        let mimeType = Static.getMimeType staticPath
        liftIO $ res $ Wai.responseFile H.status200 [(H.hContentType, mimeType)] staticPath Nothing
      AssetGenerated Html html -> do
        let s = html <> toLazy wsClientHtml <> shim
        liftIO $ res $ Wai.responseLBS H.status200 [(H.hContentType, "text/html")] s
      AssetGenerated Other s -> do
        let mimeType = Static.getMimeType $ review (fromPrism_ $ routePrism val) r
        liftIO $ res $ Wai.responseLBS H.status200 [(H.hContentType, mimeType)] s
-}