module Pages.Blog exposing (Model, Msg, page)

import Config.Data.Identity exposing (pageNames)
import Config.Data.ImageFolders as M
    exposing
        ( ImageFolder(..)
        , imagePathMaker
        )
import Config.Helpers.Articles.Article exposing (extractFirstWords)
import Config.Helpers.Articles.Markdown exposing (renderDeviceMarkdownNoToc, renderDeviceMarkdownNoTocGeneric)
import Config.Helpers.Cards.Inner.Text
    exposing
        ( detailBodyMaker
        , detailFormat
        , detailTitleMaker
        )
import Config.Helpers.Cards.Outer.Helpers exposing (cardMaker)
import Config.Helpers.Cards.Outer.Types as C exposing (Cardable(..))
import Config.Helpers.Converters
    exposing
        ( formatName
        , wordCount
        )
import Config.Helpers.Headers.Helpers exposing (headerMaker)
import Config.Helpers.Headers.Records exposing (blogHeader)
import Config.Helpers.Headers.Types as R exposing (Header)
import Config.Helpers.Response
    exposing
        ( pageList
        , topLevelContainer
        )
import Config.Helpers.Viewport exposing (resetViewport)
import Config.Pages.Blogs.MainBlog.BigFatSurprise exposing (articleBigFatSurprise)
import Config.Pages.Blogs.MainBlog.EverettVegans exposing (articleEverettVegans)
import Config.Pages.Blogs.MainBlog.FeldwitzFuckery exposing (articleFeldwitzFuckery)
import Config.Pages.Blogs.MainBlog.HunterGatherers exposing (articleHunterGatherers)
import Config.Pages.Blogs.MainBlog.MeatApologetics exposing (articleMeatApologetics)
import Config.Pages.Blogs.MainBlog.NagraGoodrich exposing (articleNagraGoodrich)
import Config.Pages.Blogs.MainBlog.PlantBasedMeta exposing (articlePlantBasedMeta)
import Config.Pages.Blogs.MainBlog.QuackSmashing exposing (articleQuackSmashing)
import Config.Pages.Blogs.MainBlog.SapienDiet exposing (articleSapienDiet)
import Config.Pages.Blogs.MainBlog.SeedOils exposing (articleSeedOils)
import Config.Pages.Blogs.MainBlog.Shenangians exposing (articleShenanigans)
import Config.Pages.Blogs.MainBlog.SweetDeception exposing (articleSweetDeception)
import Config.Pages.Blogs.Types exposing (BlogArticle)
import Config.Style.Colour.Helpers as T exposing (ThemeColor(..))
import Config.Style.Fonts
    exposing
        ( defaultFontSize
        , paragraphSpacing
        )
import Config.Style.Icons.Icons exposing (construction)
import Config.Style.Images
    exposing
        ( ElementSize(..)
        , imageSquareMaker
        )
import Effect exposing (Effect)
import Element as E
    exposing
        ( Device
        , DeviceClass(..)
        , Element
        , Orientation(..)
        , alignLeft
        , alignTop
        , column
        , el
        , none
        , paddingEach
        , px
        , row
        , text
        , width
        )
import Html.Attributes as H exposing (style)
import Layouts
import Page exposing (Page)
import Route exposing (Route)
import Route.Path as Path
import Shared exposing (Model)
import View exposing (View)


page : Shared.Model -> Route () -> Page Model Msg
page shared route =
    Page.new
        { init = init
        , update = update
        , subscriptions = subscriptions
        , view = view shared
        }
        |> Page.withLayout toLayout


toLayout : Model -> Layouts.Layout Msg
toLayout model =
    Layouts.Navbar {}



-- INIT


type alias Model =
    {}


init : () -> ( Model, Effect Msg )
init () =
    ( {}
    , Effect.map
        (\_ -> NoOp)
        (Effect.sendCmd resetViewport)
    )



-- UPDATE


type Msg
    = NoOp


update : Msg -> Model -> ( Model, Effect Msg )
update msg model =
    case msg of
        NoOp ->
            ( model
            , Effect.none
            )



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.none



-- VIEW


view : Shared.Model -> Model -> View Msg
view shared model =
    { title = pageNames.pageHyperBlog
    , attributes = []
    , element = blogContainer shared.device
    }


blogContainer : Device -> Element msg
blogContainer device =
    topLevelContainer (blogList device)


blogList : Device -> Element msg
blogList device =
    column
        (case ( device.class, device.orientation ) of
            _ ->
                pageList device
        )
    <|
        List.concat
            [ [ headerMaker (R.BlogPage blogHeader) ]
            , List.map
                (\article ->
                    cardMaker device (C.BlogCard article) (contentList device article)
                )
                [ -- articleFeldwitzFuckery
                  articleShenanigans
                , articleSweetDeception
                , articleEverettVegans
                , articleQuackSmashing
                , articleSapienDiet
                , articleNagraGoodrich
                , articleMeatApologetics
                , articleSeedOils
                , articleHunterGatherers
                , articlePlantBasedMeta
                , articleBigFatSurprise
                ]
            ]


contentList : Device -> BlogArticle -> List (Element msg)
contentList device article =
    [ articleMaker device article ]


articleImage :
    BlogArticle
    ->
        { src : String
        , description : String
        }
articleImage article =
    { src = imagePathMaker M.BlogArticle article.articleImage
    , description = article.articleName
    }


articleMaker : Device -> BlogArticle -> Element msg
articleMaker device article =
    let
        image : ElementSize -> Element msg
        image size =
            el
                [ alignLeft
                , alignTop
                , paddingEach
                    { top = 0
                    , right = 10
                    , bottom = 7
                    , left = 0
                    }
                ]
            <|
                imageSquareMaker device (imagePathMaker M.BlogCard article.articleImage) True size
    in
    detailFormat column
        [ detailFormat row
            [ case ( device.class, device.orientation ) of
                ( Phone, Portrait ) ->
                    none

                ( Tablet, Portrait ) ->
                    none

                _ ->
                    image Big
            , detailFormat column
                (articleRows article ++ [])
            ]
        , el [] <|
            detailBodyMaker TextLightGrey (renderDeviceMarkdownNoTocGeneric (extractFirstWords article.articleBody))
        ]


infoRow : String -> Element msg -> Element msg
infoRow label value =
    detailFormat row
        [ el [ width <| px 82 ] <|
            detailTitleMaker TextLightOrange label
        , detailBodyMaker TextLightGrey value
        ]


articleRows : BlogArticle -> List (Element msg)
articleRows article =
    let
        referenceCount =
            List.length article.articleReferences
    in
    [ infoRow "Published:" (text article.articlePublished)
    , infoRow "Author:" (text article.articleAuthor)
    , infoRow "Duration:"
        (text
            (String.fromInt
                (wordCount article.articleBody // 225)
                ++ " minutes"
            )
        )
    , infoRow "Words"
        (text
            (String.fromInt
                (wordCount article.articleBody)
            )
        )
    , infoRow "Sources"
        (if referenceCount >= 2 then
            text (String.fromInt referenceCount)

         else
            text "N/A"
        )
    ]
