port module Search exposing (..)

import Browser
import Html as H exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick, onInput, onSubmit)
import Markdown



-- MAIN


main : Program Flags Model Msg
main =
    Browser.element
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }



--- Model


type alias Flags =
    {}


type alias Doc =
    { body : String
    , title : String
    , id : String
    }


type alias SearchEntry =
    { ref : String
    , score : Float
    , doc : Doc
    }


type SearchState
    = Initial
    | Found (List SearchEntry)


type alias Model =
    { searchInput : String
    , results : SearchState
    , searchVisible : Bool
    }


type Msg
    = SetSearch String
    | ToggleBar
    | SubmitSearch
    | GetSearchResults (List SearchEntry)



--- Init


init : Flags -> ( Model, Cmd Msg )
init flags =
    ( { searchInput = ""
      , results = Initial
      , searchVisible = False
      }
    , Cmd.none
    )



--- Update


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ToggleBar ->
            ( { model | searchVisible = not model.searchVisible }
            , Cmd.none
            )

        SetSearch str ->
            ( { model | searchInput = str }
            , Cmd.none
            )

        SubmitSearch ->
            ( model, doSearch model.searchInput )

        GetSearchResults list ->
            ( { model | results = Found <| List.take 20 list }, Cmd.none )


subscriptions : Model -> Sub Msg
subscriptions _ =
    receiveSearch GetSearchResults



--- View


view : Model -> Html Msg
view model =
    div
        [ class " inline-flex px-4 items-center hover:bg-amber-600 hover:bg-opacity-10  dark:hover:bg-stone-800"
        ]
        [ a
            [ href "#"
            , class "h-full w-full inline-flex items-center"
            , onClick ToggleBar
            ]
            [ i [ class "fa fa-search" ] []
            ]
        , div
            [ class "absolute px-2 mx-2 right-0 max-w-screen-md rounded top-12 w-full border-l border-r border-b bg-white h-12 dark:bg-stone-800 dark:border-stone-700"
            , classList [ ( "hidden", not model.searchVisible ) ]
            ]
            [ H.form [ onSubmit SubmitSearch ]
                [ input
                    [ type_ "text"
                    , value model.searchInput
                    , autofocus True
                    , placeholder "Search …"
                    , class "w-full block h-8 border-0 border-b border-stone-400 mt-2 focus:ring-0 focus:border-indigo-500 dark:bg-stone-800 dark:focus:border-cyan-400"
                    , onInput SetSearch
                    ]
                    []
                ]
            , viewResults model.results
            ]
        ]


viewResults : SearchState -> Html Msg
viewResults state =
    case state of
        Initial ->
            span [ class "hidden" ] []

        Found [] ->
            div
                [ class "bg-white dark:bg-stone-800 mt-2 w-full"
                ]
                [ div [ class "flex flex-row items-center h-14 justify-center text-xl" ]
                    [ i [ class "fa fa-meh font-thin mr-2" ]
                        []
                    , text "No results."
                    ]
                ]

        Found entries ->
            div
                [ class "bg-white dark:bg-stone-800 mt-2 w-screen sm:w-full h-screen-12 md:h-fit md:max-h-96 overflow-auto shadow-lg border-l border-r border-b dark:border-stone-700"
                ]
                [ div [ class "px-2 pt-2 pb-1 flex flex-col divide-y dark:divide-stone-700 " ]
                    (List.map viewResult entries)
                ]


viewResult : SearchEntry -> Html Msg
viewResult result =
    div [ class "py-2 content" ]
        [ a
            [ class "text-lg font-semibold"
            , href result.ref
            ]
            [ text result.doc.title
            ]
        , Markdown.toHtml [ class "content" ] result.doc.body
        ]


textInput : String
textInput =
    " placeholder-gray-400 w-full dark:text-slate-200 dark:bg-slate-800 dark:border-slate-500 border-gray-400 rounded " ++ formFocusRing


formFocusRing : String
formFocusRing =
    " focus:ring focus:ring-black focus:ring-opacity-50 focus:ring-offset-0 dark:focus:ring-slate-400 "



--- Ports


port receiveSearch : (List SearchEntry -> msg) -> Sub msg


port doSearch : String -> Cmd msg