{-
   Copyright 2020 Eike K. & Contributors

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


module Comp.ItemMail exposing
    ( FormAction(..)
    , Model
    , Msg
    , clear
    , emptyModel
    , init
    , update
    , view2
    )

import Api
import Api.Model.EmailSettingsList exposing (EmailSettingsList)
import Api.Model.SimpleMail exposing (SimpleMail)
import Comp.Basic as B
import Comp.Dropdown
import Comp.EmailInput
import Comp.MenuBar as MB
import Data.DropdownStyle
import Data.Flags exposing (Flags)
import Data.UiSettings exposing (UiSettings)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick, onInput)
import Http
import Messages.Comp.ItemMail exposing (Texts)
import Styles as S


type alias Model =
    { connectionModel : Comp.Dropdown.Model String
    , subject : String
    , recipients : List String
    , recipientsModel : Comp.EmailInput.Model
    , ccRecipients : List String
    , ccRecipientsModel : Comp.EmailInput.Model
    , bccRecipients : List String
    , bccRecipientsModel : Comp.EmailInput.Model
    , body : String
    , attachAll : Bool
    , formError : FormError
    }


type FormError
    = FormErrorNone
    | FormErrorNoConnection
    | FormErrorHttp Http.Error


type Msg
    = SetSubject String
    | RecipientMsg Comp.EmailInput.Msg
    | CCRecipientMsg Comp.EmailInput.Msg
    | BCCRecipientMsg Comp.EmailInput.Msg
    | SetBody String
    | ConnMsg (Comp.Dropdown.Msg String)
    | ConnResp (Result Http.Error EmailSettingsList)
    | ToggleAttachAll
    | Cancel
    | Send


type alias MailInfo =
    { conn : String
    , mail : SimpleMail
    }


type FormAction
    = FormSend MailInfo
    | FormCancel
    | FormNone


emptyModel : Model
emptyModel =
    { connectionModel = Comp.Dropdown.makeSingle
    , subject = ""
    , recipients = []
    , recipientsModel = Comp.EmailInput.init
    , ccRecipients = []
    , ccRecipientsModel = Comp.EmailInput.init
    , bccRecipients = []
    , bccRecipientsModel = Comp.EmailInput.init
    , body = ""
    , attachAll = True
    , formError = FormErrorNone
    }


init : Flags -> ( Model, Cmd Msg )
init flags =
    ( emptyModel, Api.getMailSettings flags "" ConnResp )


clear : Model -> Model
clear model =
    { model
        | subject = ""
        , recipients = []
        , ccRecipients = []
        , bccRecipients = []
        , body = ""
    }


update : Flags -> Msg -> Model -> ( Model, Cmd Msg, FormAction )
update flags msg model =
    case msg of
        SetSubject str ->
            ( { model | subject = str }, Cmd.none, FormNone )

        RecipientMsg m ->
            let
                ( em, ec, rec ) =
                    Comp.EmailInput.update flags model.recipients m model.recipientsModel
            in
            ( { model
                | recipients = rec
                , recipientsModel = em
              }
            , Cmd.map RecipientMsg ec
            , FormNone
            )

        CCRecipientMsg m ->
            let
                ( em, ec, rec ) =
                    Comp.EmailInput.update flags model.ccRecipients m model.ccRecipientsModel
            in
            ( { model
                | ccRecipients = rec
                , ccRecipientsModel = em
              }
            , Cmd.map CCRecipientMsg ec
            , FormNone
            )

        BCCRecipientMsg m ->
            let
                ( em, ec, rec ) =
                    Comp.EmailInput.update flags model.bccRecipients m model.bccRecipientsModel
            in
            ( { model | bccRecipients = rec, bccRecipientsModel = em }
            , Cmd.map BCCRecipientMsg ec
            , FormNone
            )

        SetBody str ->
            ( { model | body = str }, Cmd.none, FormNone )

        ConnMsg m ->
            let
                ( cm, _ ) =
                    -- dropdown doesn't use cmd!!
                    Comp.Dropdown.update m model.connectionModel
            in
            ( { model | connectionModel = cm }, Cmd.none, FormNone )

        ToggleAttachAll ->
            ( { model | attachAll = not model.attachAll }, Cmd.none, FormNone )

        ConnResp (Ok list) ->
            let
                names =
                    List.map .name list.items

                cm =
                    Comp.Dropdown.makeSingleList
                        { options = names
                        , selected = List.head names
                        }
            in
            ( { model
                | connectionModel = cm
                , formError =
                    if names == [] then
                        FormErrorNoConnection

                    else
                        FormErrorNone
              }
            , Cmd.none
            , FormNone
            )

        ConnResp (Err err) ->
            ( { model | formError = FormErrorHttp err }, Cmd.none, FormNone )

        Cancel ->
            ( model, Cmd.none, FormCancel )

        Send ->
            case ( model.formError, Comp.Dropdown.getSelected model.connectionModel ) of
                ( FormErrorNone, conn :: [] ) ->
                    let
                        emptyMail =
                            Api.Model.SimpleMail.empty

                        sm =
                            { emptyMail
                                | recipients = model.recipients
                                , cc = model.ccRecipients
                                , bcc = model.bccRecipients
                                , subject = model.subject
                                , body = model.body
                                , addAllAttachments = model.attachAll
                            }
                    in
                    ( model, Cmd.none, FormSend { conn = conn, mail = sm } )

                _ ->
                    ( model, Cmd.none, FormNone )


isValid : Model -> Bool
isValid model =
    model.recipients
        /= []
        && model.subject
        /= ""
        && model.body
        /= ""
        && model.formError
        == FormErrorNone
        && Comp.Dropdown.getSelected model.connectionModel
        /= []



--- View2


view2 : Texts -> UiSettings -> Model -> Html Msg
view2 texts settings model =
    let
        dds =
            Data.DropdownStyle.mainStyle

        connectionCfg =
            { makeOption = \a -> { text = a, additional = "" }
            , placeholder = texts.selectConnection
            , labelColor = \_ -> \_ -> ""
            , style = dds
            }
    in
    div
        [ class "flex flex-col"
        ]
        [ div [ class "mb-4" ]
            [ label [ class S.inputLabel ]
                [ text texts.sendVia
                , B.inputRequired
                ]
            , Html.map ConnMsg
                (Comp.Dropdown.view2
                    connectionCfg
                    settings
                    model.connectionModel
                )
            ]
        , div
            [ class S.errorMessage
            , classList [ ( "hidden", model.formError == FormErrorNone ) ]
            ]
            [ case model.formError of
                FormErrorNone ->
                    text ""

                FormErrorHttp err ->
                    text (texts.httpError err)

                FormErrorNoConnection ->
                    text texts.connectionMissing
            ]
        , div [ class "mb-4" ]
            [ label
                [ class S.inputLabel
                ]
                [ text texts.recipients
                , B.inputRequired
                ]
            , Html.map RecipientMsg
                (Comp.EmailInput.view2 { style = dds, placeholder = appendDots texts.recipients }
                    model.recipients
                    model.recipientsModel
                )
            ]
        , div [ class "mb-4" ]
            [ label [ class S.inputLabel ]
                [ text texts.ccRecipients
                ]
            , Html.map CCRecipientMsg
                (Comp.EmailInput.view2 { style = dds, placeholder = appendDots texts.ccRecipients }
                    model.ccRecipients
                    model.ccRecipientsModel
                )
            ]
        , div [ class "mb-4" ]
            [ label [ class S.inputLabel ]
                [ text texts.bccRecipients
                ]
            , Html.map BCCRecipientMsg
                (Comp.EmailInput.view2 { style = dds, placeholder = appendDots texts.bccRecipients }
                    model.bccRecipients
                    model.bccRecipientsModel
                )
            ]
        , div [ class "mb-4" ]
            [ label [ class S.inputLabel ]
                [ text texts.subject
                , B.inputRequired
                ]
            , input
                [ type_ "text"
                , class S.textInput
                , onInput SetSubject
                , value model.subject
                ]
                []
            ]
        , div [ class "mb-4" ]
            [ label [ class S.inputLabel ]
                [ text texts.body
                , B.inputRequired
                ]
            , textarea
                [ onInput SetBody
                , value model.body
                , class S.textAreaInput
                ]
                []
            ]
        , MB.viewItem <|
            MB.Checkbox
                { tagger = \_ -> ToggleAttachAll
                , label = texts.includeAllAttachments
                , value = model.attachAll
                , id = "item-send-mail-attach-all"
                }
        , div [ class "flex flex-row space-x-2" ]
            [ B.primaryButton
                { label = texts.sendLabel
                , icon = "fa fa-paper-plane font-thin"
                , handler = onClick Send
                , attrs = [ href "#" ]
                , disabled = not (isValid model)
                }
            , B.secondaryButton
                { label = texts.basics.cancel
                , icon = "fa fa-times"
                , handler = onClick Cancel
                , attrs = [ href "#" ]
                , disabled = False
                }
            ]
        ]


appendDots : String -> String
appendDots name =
    name ++ "…"
