{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE OverloadedStrings #-}


module Shpadoinkle.Backend.Static ( renderStatic ) where


import           Control.Compactable
import           Data.Monoid         ((<>))
import           Data.Text

import           Shpadoinkle         hiding (name, props, text)


renderStatic :: Html m a -> Text
renderStatic = \case
  Node tag props _ | isSelfClosing tag
                     -> renderSelfClosing tag props
  Node tag props cs  -> renderWrapping tag props cs
  Potato _           -> mempty
  TextNode t         -> t


isSelfClosing :: Text -> Bool
isSelfClosing = flip elem
  [ "area", "base", "br", "embed", "hr", "iframe"
  , "img", "input", "link", "meta", "param", "source", "track" ]


renderWrapping :: Text -> [(Text, Prop m a)] -> [Html m a] -> Text
renderWrapping tag props cs = renderOpening tag props <> ">"
  <> mconcat (renderStatic <$> cs) <> "</" <> tag <> ">"


renderSelfClosing :: Text -> [(Text, Prop m a)] -> Text
renderSelfClosing tag props = renderOpening tag props <> " />"


renderOpening :: Text -> [(Text, Prop m a)] -> Text
renderOpening tag props = let ps = renderProps props in
  "<" <> tag <> (if Data.Text.null ps then mempty else " " <> ps)


renderProps :: [(Text, Prop m a)] -> Text
renderProps = Data.Text.unwords . fmapMaybe (uncurry renderProp)


renderProp :: Text -> Prop m a -> Maybe Text
renderProp name = \case
  PListener _ -> Nothing
  PText t     -> Just $ name <> "=\"" <> t <> "\""
  PFlag True  -> Just name
  PFlag False -> Nothing