{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}

module Literate.Web.Live.Common where

import Data.ByteString qualified as BS
import Data.ByteString.Lazy qualified as BSL
import Data.FileEmbed
import Data.Function (($), (.))
import Data.Functor ((<$>))
import Data.Semigroup (Semigroup (..))
import Data.Text (Text)
import Data.Text qualified as Text
import Data.Text.Encoding qualified as Text
import Data.Text.Lazy qualified as TextL
import Data.Text.Lazy.Encoding qualified as TextL
import System.IO qualified as Sys

import Literate.Web qualified as Web
import Text.Show (Show)

{-
renderCatchingErrors ::
  forall r m.
  ( MonadLoggerIO m
  , MonadUnliftIO m
  , EmaStaticSite r
  ) =>
  RouteModel r ->
  r ->
  m (Asset BSL.ByteString)
renderCatchingErrors m r =
  catch (siteOutput (fromPrism_ $ routePrism m) m r) $ \(err :: SomeException) -> do
    -- Log the error first.
    logErrorNS "App" $ show @Text err
    pure
      $ AssetGenerated Html
        . mkHtmlErrorMsg
      $ show @Text err

-- Decode an URL path into a route
--
-- This function is used only in live server. If the route is not
-- isomoprhic, this returns a Left, with the mismatched encoding.
decodeUrlRoute ::
  forall r.
  (Eq r, Show r, IsRoute r) =>
  RouteModel r ->
  Text ->
  Either (BadRouteEncoding r) (Maybe r)
decodeUrlRoute m (urlToFilePath -> s) = do
  case checkRoutePrismGivenFilePath routePrism m s of
    Left (r, log) -> Left $ BadRouteEncoding s r log
    Right mr -> Right mr
-}

-- | A basic error response for displaying in the browser
liveErrorHtmlResponse :: Text -> BSL.ByteString
liveErrorHtmlResponse err = mkHtmlErrorMsg err <> BSL.fromStrict wsClientHtml

urlToFilePath :: Text -> Sys.FilePath
urlToFilePath = Text.unpack . Text.intercalate "/" . (Web.encodePathSegment . Web.decodePathSegment <$>) . Text.splitOn "/"

mkHtmlErrorMsg :: Text -> BSL.ByteString
mkHtmlErrorMsg s = TextL.encodeUtf8 $ TextL.replace "MESSAGE" (TextL.fromStrict s) $ TextL.fromStrict $ Text.decodeUtf8 $ emaErrorHtml

emaErrorHtml :: BS.ByteString
emaErrorHtml = $(embedFile "www/live-error.html")

decodeRouteNothingMsg :: Text
decodeRouteNothingMsg = "Literate.Web.Live: 404 (route decoding returned Nothing)"

data BadRouteEncoding r = BadRouteEncoding
  { _bre_urlFilePath :: Sys.FilePath
  , _bre_decodedRoute :: r
  , _bre_checkLog :: [(Sys.FilePath, Text)]
  }
  deriving stock (Show)

wsClientHtml :: BS.ByteString
wsClientHtml = $(embedFile "www/live-indicator.html")

{-
badRouteEncodingMsg :: (Show r) => BadRouteEncoding r -> Text
badRouteEncodingMsg BadRouteEncoding {..} =
  toText $
    "A route Prism' is unlawful.\n\nThe URL '"
      <> toText _bre_urlFilePath
      <> "' decodes to route '"
      <> show _bre_decodedRoute
      <> "', but it is not isomporphic on any of the allowed candidates: \n\n"
      <> Text.intercalate
        "\n\n"
        ( _bre_checkLog <&> \(candidate, log) ->
            "## Candidate '" <> toText candidate <> "':\n" <> log
        )
      <> " \n\nYou should make the relevant routePrism lawful to fix this issue."
-}