{-
   Copyright 2020 Eike K. & Contributors

   SPDX-License-Identifier: AGPL-3.0-or-later
-}


module Comp.BoxQueryView exposing (Model, Msg, init, reloadData, update, view)

import Api
import Api.Model.ItemLight exposing (ItemLight)
import Api.Model.ItemLightList exposing (ItemLightList)
import Api.Model.ItemQuery exposing (ItemQuery)
import Comp.Basic
import Comp.ItemColumnView
import Data.BoxContent exposing (QueryData, SearchQuery(..))
import Data.Flags exposing (Flags)
import Data.ItemColumn as IC exposing (ItemColumn)
import Data.Items
import Data.SearchMode
import Data.UiSettings exposing (UiSettings)
import Html exposing (Html, a, div, i, table, tbody, td, text, th, thead, tr)
import Html.Attributes exposing (class, classList)
import Http
import Messages.Comp.BoxQueryView exposing (Texts)
import Page exposing (Page(..))
import Styles


type alias Model =
    { results : ViewResult
    , meta : QueryData
    }


type ViewResult
    = Loading
    | Loaded ItemLightList
    | Failed Http.Error


type Msg
    = ItemsResp (Result Http.Error ItemLightList)
    | ReloadData


init : Flags -> QueryData -> ( Model, Cmd Msg )
init flags data =
    ( { results = Loading
      , meta = data
      }
    , dataCmd flags data
    )


reloadData : Msg
reloadData =
    ReloadData



--- Update


update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Bool )
update flags msg model =
    case msg of
        ItemsResp (Ok list) ->
            ( { model | results = Loaded list }, Cmd.none, False )

        ItemsResp (Err err) ->
            ( { model | results = Failed err }, Cmd.none, False )

        ReloadData ->
            ( model, dataCmd flags model.meta, True )



--- View


view : Texts -> UiSettings -> Model -> Html Msg
view texts settings model =
    case model.results of
        Loading ->
            div [ class "h-24 " ]
                [ Comp.Basic.loadingDimmer
                    { label = ""
                    , active = True
                    }
                ]

        Failed err ->
            div
                [ class "py-4"
                , class Styles.errorMessage
                ]
                [ text texts.errorOccurred
                , text ": "
                , text (texts.httpError err)
                ]

        Loaded list ->
            if list.groups == [] then
                viewEmpty texts

            else
                viewItems texts settings model.meta list


viewItems : Texts -> UiSettings -> QueryData -> ItemLightList -> Html Msg
viewItems texts settings meta list =
    let
        items =
            Data.Items.flatten list
    in
    table [ class "w-full divide-y divide-y-2 dark:divide-slate-500" ]
        (viewItemHead texts meta ++ [ tbody [ class "divide-y divide-dotted dark:divide-slate-500" ] <| List.map (viewItemRow texts settings meta) items ])


viewItemHead : Texts -> QueryData -> List (Html Msg)
viewItemHead texts meta =
    let
        ( col1, cols ) =
            getColumns meta

        isSecond n =
            n == 1

        isNotLast n =
            n > 1 && n < List.length cols
    in
    if not meta.showHeaders then
        []

    else
        [ thead []
            [ tr []
                (List.map texts.itemColumn.header (col1 :: cols)
                    |> List.indexedMap
                        (\index ->
                            \n ->
                                th
                                    [ class "text-left text-sm"
                                    , classList
                                        [ ( "hidden sm:table-cell", isSecond index )
                                        , ( "hidden md:table-cell", isNotLast index )
                                        ]
                                    ]
                                    [ text n ]
                        )
                )
            ]
        ]


viewItemRow : Texts -> UiSettings -> QueryData -> ItemLight -> Html Msg
viewItemRow texts settings meta item =
    let
        ( col1, cols ) =
            getColumns meta

        isSecond n =
            n == 0

        isNotLast n =
            n > 0 && n < (List.length cols - 1)

        render col =
            Comp.ItemColumnView.renderDiv
                texts.templateCtx
                settings
                col
                [ class "flex flex-row break-all flex-wrap space-x-1" ]
                item

        td1 =
            td [ class "py-2 px-1" ]
                [ a
                    [ class Styles.link
                    , Page.href (ItemDetailPage item.id)
                    ]
                    [ render col1
                    ]
                ]

        tdRem index col =
            td
                [ class "py-1 px-1"
                , classList
                    [ ( "hidden sm:table-cell", isSecond index )
                    , ( "hidden md:table-cell", isNotLast index )
                    ]
                ]
                [ render col
                ]
    in
    tr []
        (td1 :: List.indexedMap tdRem cols)


viewEmpty : Texts -> Html Msg
viewEmpty texts =
    div [ class "flex justify-center items-center h-full" ]
        [ div [ class "px-4 py-4 text-center align-middle text-lg" ]
            [ i [ class "fa fa-smile font-thin mr-2" ] []
            , text texts.noResults
            ]
        ]



--- Helpers


getColumns : QueryData -> ( ItemColumn, List ItemColumn )
getColumns meta =
    case meta.columns of
        x :: xs ->
            ( x, xs )

        [] ->
            ( IC.Name, [ IC.Correspondent, IC.DateShort ] )


mkQuery : String -> QueryData -> ItemQuery
mkQuery q meta =
    { query = q
    , limit = Just meta.limit
    , offset = Nothing
    , searchMode = Just <| Data.SearchMode.asString Data.SearchMode.Normal
    , withDetails = Just meta.details
    }


dataCmd : Flags -> QueryData -> Cmd Msg
dataCmd flags data =
    case data.query of
        SearchQueryString q ->
            Api.itemSearch flags (mkQuery q data) ItemsResp

        SearchQueryBookmark bmId ->
            Api.itemSearchBookmark flags (mkQuery bmId data) ItemsResp
