{-|
Module      : TTN.View.Article
Description : Code for rendering article-related pages.
Author      : Sam van Herwaarden <samvherwaarden@protonmail.com>
-}

{-# LANGUAGE OverloadedStrings #-}

module TTN.View.Article where

import TTN.Routes

import TTN.Controller.Shared
import TTN.Model.Article
import TTN.Model.Core
import TTN.Model.Language
import TTN.Model.Translation
import TTN.View.Core                    ( renderSimpleStr ) -- TODO: This should go
import TTN.View.Shared
import TTN.View.User

import Control.Monad                    ( forM_ )
import Control.Monad.Trans.Class        ( lift )
import Data.Maybe                       ( fromMaybe )
import Data.Monoid                      ( (<>) )
import Data.Text                        ( Text, pack )
import Data.Time.Format                 ( FormatTime
                                        , defaultTimeLocale
                                        , formatTime )

import Lucid

import Text.Digestive.Form
import Text.Digestive.View

import Database.Persist

import qualified Text.Digestive.Lucid.Html5 as DL

-- | Render the body of an Article or Translation
renderBody :: [[(Int, Text)]] -> TTNView ctx ()
renderBody b = mapM_ (p_ . toHtml) $ bodyAsParagraphs b

-- * Article views

-- | Generate HTML for new/edit article form
renderArticleForm :: Text -> View (TTNView ctx ()) -> TTNView ctx ()
renderArticleForm target view = div_ [id_ "new-article-form"] $ do 
        h2_ "Article"
        form_ [method_ "post", action_ target] $ do
              DL.errorList "article" view
              inputText_ "article.pub_date" "Publication date (yyyy-mm-dd)" view
              inputText_ "article.title"    "Title"    view
              inputText_ "article.author"   "Author"   view
              inputText_ "article.url"      "URL"      view
              inputSelect_ "article.language" "Language" view
              inputTextArea_ (Just 5)  (Just 100) "article.summary"  "Summary"  view
              inputTextArea_ (Just 25) (Just 100) "article.body" "Body" view
              csrf
              submit "Submit article"

getTime :: FormatTime t => t -> String
getTime = formatTime defaultTimeLocale "%e %B %Y, %H:%M"

-- | Generate HTML for showing an Article
renderArticle :: Entity Article -> TTNBlockDef ctx
renderArticle ea@(Entity key a) = blockDef
  where blockDef TTNContent = div_ [id_ "view-article"] $ do
            articleHead ea
            -- Switched off for now
            -- div_ [id_ "edit-article-link"] . a_ [href_ $ editArticlePath a] $
                -- h "Edit article"
            maybe (return ()) (p_ . strong_ . toHtml) $ articleSummary a
            renderBody $ articleBody a
            articleFooter ea
        blockDef other      = defaultBlocks other

articleHead :: Entity Article -> TTNView ctx ()
articleHead (Entity key a) = do
    -- p_ . em_ . toHtml $ "Submitted " <> (getTime $ artCreated a)
    -- p_ . em_ . toHtml $ "Last edited " <> (getTime $ artModified a)
    h2_ . toHtml $ articleTitle a
    div_ [class_ "art-time-author"] . em_ $ do
      h $ articlePubDate a <> " - " <> articleAuthor a <> " - "
      a_ [href_ $ articleUrl a, target_ "_blank"] $ h "Original"

articleFooter :: Entity Article -> TTNView ctx ()
articleFooter ea@(Entity key a) = do
    div_ [class_ "user-badge"] $ do h "Contributed by "
                                    renderProfileBadge $ articleContrId a
    div_ [id_ "available-translations"] $ do h "Available translations: "
                                             mapM_ translationLink $ articleAvTrans a
    div_ [id_ "translate-to"] $ do h "Translate to:"
                                   mapM_ translateLink allLanguages
  where translationLink :: Language -> TTNView ctx ()
        translationLink l = div_ [class_ "translation-link"] $
                              a_ [href_ $ viewTranslationPath ea l] $ toHtml l
        translateLink :: Language -> TTNView ctx ()
        translateLink l = div_ [class_ "translate-link"] $
                            a_ [href_ $ newTranslationPath ea l] $ toHtml l

-- | For use in listings
renderListArticle :: Entity Article -> TTNView ctx ()
renderListArticle ea@(Entity aid a) =
    div_ [class_ "list-elem article"] $ do
      h3_ . a_ [href_ (viewArticlePath ea)] . toHtml $ articleTitle a
      p_ [class_ "list-article-summary"] . h . fromMaybe "" $ articleSummary a
      div_ [class_ "article-meta"] . em_ $ do
          h (articlePubDate a <> " - " <> articleAuthor a <> " - ")
          a_ [href_ $ articleUrl a, target_ "_blank"] "Original"

renderArticleList :: [Entity Article] -> TTNBlockDef ctx
renderArticleList as = blockDef
  where blockDef TTNContent = do
          div_ [id_ "new-article-link"] . a_ [href_ newArticlePath] $ h "Add article"
          mapM_ renderListArticle as
        blockDef other      = defaultBlocks other

-- * Translation views

-- | Generate HTML for new-Translation form. 'listSubViews' deals with
--   fields generated by 'listOf'. There is some hacky magic going on here
--   for getting the sentences from the original article (they are stored
--   in form fields which do not accept data). (See 'mkTranslateForm' in
--   TTN.Controller.Article)
renderTranslate :: Entity Article
                -> Language
                -> Text
                -> View (TTNView ctx ())
                -> TTNView ctx ()
renderTranslate ea@(Entity aid art) lang target view =
    div_ [id_ "translation-form"] . form_ [method_ "post", action_ target] $ do
        DL.errorList "translate" view
        div_ [id_ "gt-link"] $ renderGTranslate (articleOrigLang art) lang
                                                (articleUrl art)
                                                "View on Google Translate"
        div_ [id_ "auto-link"] . a_ [href_ $ autoTranslationPath ea lang] $
                                      h "Pre-fill with Bing translate (slow)"
        h3_ $ h "Title"
        toHtml $ articleTitle art
        inputText_ "translate.title" "" view
        h3_ $ h "Summary"
        toHtml . fromMaybe "" $ articleSummary art
        inputTextArea_ (Just 5) (Just 110) "translate.summary" "" view
        h3_ $ h "Body"
        forM_ (listSubViews "translate.body" view) $ \v' ->
          div_ [class_ "body-par"] $ forM_ (listSubViews "paragraph" v') $ \v ->
              div_ [class_ "body-sentence"] $ do
                  DL.label "translation" v (toHtml $ fieldInputText "original" v) 
                  DL.inputTextArea (Just 2) (Just 110) "translation" v
                  DL.errorList "translation" v
        csrf
        submit "Submit translation"

-- | Generate HTML for showing a translation
renderTranslation :: Entity Article -> [Entity Translation] -> TTNBlockDef ctx
renderTranslation ea ts = blockDef
  where blockDef TTNContent = mapM_ (renderSingleTrans ea) ts
        blockDef other      = defaultBlocks other

-- TODO: This is not quite right here
renderSingleTrans :: Entity Article -> Entity Translation -> TTNView ctx ()
renderSingleTrans ea@(Entity aid a) et@(Entity tid t) = do
    -- p_ . em_ . toHtml $ "Submitted " <> show (translationCreated t)
    h2_ . toHtml $ translationTitle t
    p_ . em_ . toHtml $ (articlePubDate a <> " - " <> articleAuthor a)
    p_ . a_ [href_ $ articleUrl a] . h $ "Original: " <> articleTitle a
    maybe (return ()) (p_ . strong_ . toHtml) $ translationSummary t
    renderBody $ translationBody t
    div_ [class_ "user-badge"] $ do h "Contributed by "
                                    renderProfileBadge $ translationContrId t
    div_ [id_ "original-link"] $ renderGTranslate (articleOrigLang a)
                                                  (translationLang t)
                                                  (articleUrl a)
                                                  "View on Google Translate"

-- | For use in listings
renderListTrans :: Entity Article -> Entity Translation -> TTNView ctx ()
renderListTrans ea@(Entity aid a) et@(Entity tid t) =
    div_ [class_ "list-elem translation"] $ do
      h3_ . a_ [href_ (viewTranslationPath ea (translationLang t))] . toHtml $
          translationTitle t
      p_ [class_ "list-translation-summary"] . h . fromMaybe "" $
          translationSummary t
      div_ [class_ "translation-meta"] . em_ $ do
          h (articlePubDate a <> " - " <> articleAuthor a <> " - ")
          a_ [href_ $ articleUrl a, target_ "_blank"] "Original"

-- TODO: This function is ugly
renderTrans :: [Entity Translation] -> TTNBlockDef ctx
renderTrans ts = blockDef
  where renderSingle et@(Entity tid t) = do
          a' <- lift . getArticleById $ translationArtId t
          a <- maybe (lift $ renderSimpleStr "Something strange happened!") -- TODO: set right
                     return a'
          renderListTrans a et
        blockDef TTNContent = if null ts
            then p_ $ h "No translations found... Feel free to contribute!"
            else mapM_ renderSingle ts
        blockDef other      = defaultBlocks other
          
-- * Google Translate URLs

-- | Generate URL for Google Translate version
mkGTranslateURL :: Language -> Language -> Text -> Text
mkGTranslateURL source target article_url =
    "https://translate.google.com/translate?sl=" <> langCode source <>
      "&tl=" <> langCode target <> "&ie=UTF-8&u=" <> article_url

-- | Generate hyperlink
renderGTranslate :: Language -> Language -> Text -> Text -> TTNView ctx ()
renderGTranslate from to url label =
    a_ [href_ (mkGTranslateURL from to url), target_ "_blank"] $ toHtml label

