{-
   Copyright 2020 Eike K. & Contributors

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


module Comp.FolderDetail exposing
    ( Model
    , Msg
    , init
    , initEmpty
    , update
    , view2
    )

import Api
import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.FolderDetail exposing (FolderDetail)
import Api.Model.IdName exposing (IdName)
import Api.Model.IdResult exposing (IdResult)
import Api.Model.NewFolder exposing (NewFolder)
import Api.Model.User exposing (User)
import Comp.Basic as B
import Comp.FixedDropdown
import Comp.MenuBar as MB
import Comp.YesNoDimmer
import Data.DropdownStyle as DS
import Data.Flags exposing (Flags)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick, onInput)
import Http
import Messages.Comp.FolderDetail exposing (Texts)
import Styles as S
import Util.Maybe


type alias Model =
    { formState : FormState
    , folder : FolderDetail
    , name : Maybe String
    , members : List IdName
    , users : List User
    , memberDropdown : Comp.FixedDropdown.Model IdName
    , selectedMember : Maybe IdName
    , loading : Bool
    , deleteDimmer : Comp.YesNoDimmer.Model
    }


type FormState
    = FormStateInitial
    | FormStateHttpError Http.Error
    | FormStateFolderCreated
    | FormStateGenericError String
    | FormStateNameChangeSuccessful
    | FormStateDeleteSuccessful


isError : FormState -> Bool
isError state =
    case state of
        FormStateInitial ->
            False

        FormStateHttpError _ ->
            True

        FormStateGenericError _ ->
            True

        FormStateFolderCreated ->
            False

        FormStateNameChangeSuccessful ->
            False

        FormStateDeleteSuccessful ->
            False


isSuccess : FormState -> Bool
isSuccess state =
    case state of
        FormStateInitial ->
            False

        FormStateHttpError _ ->
            False

        FormStateGenericError _ ->
            False

        FormStateFolderCreated ->
            True

        FormStateNameChangeSuccessful ->
            True

        FormStateDeleteSuccessful ->
            True


type Msg
    = SetName String
    | MemberDropdownMsg (Comp.FixedDropdown.Msg IdName)
    | SaveName
    | NewFolderResp (Result Http.Error IdResult)
    | ChangeFolderResp (Result Http.Error BasicResult)
    | ChangeNameResp (Result Http.Error BasicResult)
    | FolderDetailResp (Result Http.Error FolderDetail)
    | AddMember
    | RemoveMember IdName
    | RequestDelete
    | DeleteMsg Comp.YesNoDimmer.Msg
    | DeleteResp (Result Http.Error BasicResult)
    | GoBack


init : List User -> FolderDetail -> Model
init users folder =
    { formState = FormStateInitial
    , folder = folder
    , name = Util.Maybe.fromString folder.name
    , members = folder.members
    , users = users
    , memberDropdown =
        Comp.FixedDropdown.init (makeOptions users folder)
    , selectedMember = Nothing
    , loading = False
    , deleteDimmer = Comp.YesNoDimmer.emptyModel
    }


initEmpty : List User -> Model
initEmpty users =
    init users Api.Model.FolderDetail.empty


makeOptions : List User -> FolderDetail -> List IdName
makeOptions users folder =
    let
        toIdName u =
            IdName u.id u.login

        notMember idn =
            List.member idn (folder.owner :: folder.members) |> not
    in
    List.map toIdName users
        |> List.filter notMember



--- Update


update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Bool )
update flags msg model =
    case msg of
        GoBack ->
            ( model, Cmd.none, True )

        SetName str ->
            ( { model | name = Util.Maybe.fromString str }
            , Cmd.none
            , False
            )

        MemberDropdownMsg lmsg ->
            let
                ( mm, sel ) =
                    Comp.FixedDropdown.update lmsg model.memberDropdown
            in
            ( { model
                | memberDropdown = mm
                , selectedMember =
                    case sel of
                        Just _ ->
                            sel

                        Nothing ->
                            model.selectedMember
              }
            , Cmd.none
            , False
            )

        SaveName ->
            case model.name of
                Just name ->
                    let
                        cmd =
                            if model.folder.id == "" then
                                Api.createNewFolder flags (NewFolder name) NewFolderResp

                            else
                                Api.changeFolderName flags
                                    model.folder.id
                                    (NewFolder name)
                                    ChangeNameResp
                    in
                    ( { model
                        | loading = True
                        , formState = FormStateInitial
                      }
                    , cmd
                    , False
                    )

                Nothing ->
                    ( model, Cmd.none, False )

        NewFolderResp (Ok ir) ->
            if ir.success then
                ( model, Api.getFolderDetail flags ir.id FolderDetailResp, False )

            else
                ( { model
                    | loading = False
                    , formState =
                        if ir.success then
                            FormStateFolderCreated

                        else
                            FormStateGenericError ir.message
                  }
                , Cmd.none
                , False
                )

        NewFolderResp (Err err) ->
            ( { model
                | loading = False
                , formState = FormStateHttpError err
              }
            , Cmd.none
            , False
            )

        ChangeFolderResp (Ok r) ->
            if r.success then
                ( model
                , Api.getFolderDetail flags model.folder.id FolderDetailResp
                , False
                )

            else
                ( { model | loading = False, formState = FormStateGenericError r.message }
                , Cmd.none
                , False
                )

        ChangeFolderResp (Err err) ->
            ( { model
                | loading = False
                , formState = FormStateHttpError err
              }
            , Cmd.none
            , False
            )

        ChangeNameResp (Ok r) ->
            let
                model_ =
                    { model
                        | formState =
                            if r.success then
                                FormStateNameChangeSuccessful

                            else
                                FormStateGenericError r.message
                        , loading = False
                    }
            in
            ( model_, Cmd.none, False )

        ChangeNameResp (Err err) ->
            ( { model
                | formState = FormStateHttpError err
                , loading = False
              }
            , Cmd.none
            , False
            )

        FolderDetailResp (Ok sd) ->
            ( init model.users sd, Cmd.none, False )

        FolderDetailResp (Err err) ->
            ( { model
                | loading = False
                , formState = FormStateHttpError err
              }
            , Cmd.none
            , False
            )

        AddMember ->
            case model.selectedMember of
                Just mem ->
                    ( { model | loading = True }
                    , Api.addMember flags model.folder.id mem.id ChangeFolderResp
                    , False
                    )

                Nothing ->
                    ( model, Cmd.none, False )

        RemoveMember idname ->
            ( { model | loading = True }
            , Api.removeMember flags model.folder.id idname.id ChangeFolderResp
            , False
            )

        RequestDelete ->
            let
                ( dm, _ ) =
                    Comp.YesNoDimmer.update Comp.YesNoDimmer.activate model.deleteDimmer
            in
            ( { model | deleteDimmer = dm }, Cmd.none, False )

        DeleteMsg lm ->
            let
                ( dm, flag ) =
                    Comp.YesNoDimmer.update lm model.deleteDimmer

                cmd =
                    if flag then
                        Api.deleteFolder flags model.folder.id DeleteResp

                    else
                        Cmd.none
            in
            ( { model | deleteDimmer = dm }, cmd, False )

        DeleteResp (Ok r) ->
            ( { model
                | formState =
                    if r.success then
                        FormStateDeleteSuccessful

                    else
                        FormStateGenericError r.message
              }
            , Cmd.none
            , r.success
            )

        DeleteResp (Err err) ->
            ( { model | formState = FormStateHttpError err }
            , Cmd.none
            , False
            )



--- View2


view2 : Texts -> Flags -> Model -> Html Msg
view2 texts flags model =
    let
        isOwner =
            Maybe.map .user flags.account
                |> Maybe.map ((==) model.folder.owner.name)
                |> Maybe.withDefault False

        dimmerSettings : Comp.YesNoDimmer.Settings
        dimmerSettings =
            Comp.YesNoDimmer.defaultSettings texts.reallyDeleteThisFolder
                texts.basics.yes
                texts.basics.no
    in
    div [ class "flex flex-col md:relative" ]
        ([ viewButtons2 texts model
         , Html.map DeleteMsg
            (Comp.YesNoDimmer.viewN
                True
                dimmerSettings
                model.deleteDimmer
            )
         , div
            [ class "py-2 text-lg opacity-75"
            , classList [ ( "hidden", model.folder.id /= "" ) ]
            ]
            [ text texts.autoOwnerInfo
            ]
         , div
            [ class "py-2 text-lg opacity-75"
            , classList [ ( "hidden", model.folder.id == "" ) ]
            ]
            [ text texts.modifyInfo
            ]
         , div
            [ class S.message
            , classList [ ( "hidden", model.folder.id == "" || isOwner ) ]
            ]
            [ text texts.notOwnerInfo
            ]
         , div [ class "mb-4 flex flex-col" ]
            [ label
                [ class S.inputLabel
                , for "folder-name"
                ]
                [ text texts.basics.name
                , B.inputRequired
                ]
            , div [ class "flex flex-row space-x-2" ]
                [ input
                    [ type_ "text"
                    , onInput SetName
                    , Maybe.withDefault "" model.name
                        |> value
                    , classList [ ( S.inputErrorBorder, model.name == Nothing ) ]
                    , class S.textInput
                    , id "folder-name"
                    ]
                    []
                , a
                    [ class S.primaryButton
                    , class "rounded-r -ml-1"
                    , onClick SaveName
                    , href "#"
                    ]
                    [ i [ class "fa fa-save" ] []
                    , span [ class "ml-2 hidden sm:inline" ]
                        [ text texts.basics.submit
                        ]
                    ]
                ]
            ]
         , div
            [ classList
                [ ( "hidden", model.formState == FormStateInitial )
                , ( S.errorMessage, isError model.formState )
                , ( S.successMessage, isSuccess model.formState )
                ]
            , class "my-4"
            ]
            [ case model.formState of
                FormStateInitial ->
                    text ""

                FormStateHttpError err ->
                    text (texts.httpError err)

                FormStateGenericError m ->
                    text m

                FormStateFolderCreated ->
                    text texts.folderCreated

                FormStateNameChangeSuccessful ->
                    text texts.nameChangeSuccessful

                FormStateDeleteSuccessful ->
                    text texts.deleteSuccessful
            ]
         ]
            ++ viewMembers2 texts model
        )


viewMembers2 : Texts -> Model -> List (Html Msg)
viewMembers2 texts model =
    let
        folderCfg =
            { display = .name
            , icon = \_ -> Nothing
            , style = DS.mainStyle
            , selectPlaceholder = texts.basics.selectPlaceholder
            }
    in
    if model.folder.id == "" then
        []

    else
        [ div
            [ class S.header3
            , class "mt-4"
            ]
            [ text texts.members
            ]
        , div [ class "flex flex-col space-y-2" ]
            [ div [ class "flex flex-row space-x-2" ]
                [ div [ class "flex-grow" ]
                    [ Html.map MemberDropdownMsg
                        (Comp.FixedDropdown.viewStyled2
                            folderCfg
                            False
                            model.selectedMember
                            model.memberDropdown
                        )
                    ]
                , a
                    [ title texts.addMember
                    , onClick AddMember
                    , class S.primaryButton
                    , href "#"
                    , class "flex-none"
                    ]
                    [ i [ class "fa fa-plus" ] []
                    , span [ class "ml-2 hidden sm:inline" ]
                        [ text texts.add
                        ]
                    ]
                ]
            ]
        , div
            [ class "flex flex-col space-y-4 md:space-y-2 mt-2"
            , class "px-2 border-0 border-l dark:border-slate-600"
            ]
            (List.map (viewMember2 texts) model.members)
        ]


viewMember2 : Texts -> IdName -> Html Msg
viewMember2 texts member =
    div
        [ class "flex flex-row space-x-2 items-center"
        ]
        [ a
            [ class S.deleteLabel
            , href "#"
            , title texts.removeMember
            , onClick (RemoveMember member)
            ]
            [ i [ class "fa fa-trash " ] []
            ]
        , span [ class "ml-2" ]
            [ text member.name
            ]
        ]


viewButtons2 : Texts -> Model -> Html Msg
viewButtons2 texts model =
    MB.view
        { start =
            [ MB.SecondaryButton
                { tagger = GoBack
                , label = texts.basics.cancel
                , icon = Just "fa fa-arrow-left"
                , title = texts.basics.backToList
                }
            ]
        , end =
            [ MB.CustomButton
                { tagger = RequestDelete
                , label = texts.basics.delete
                , icon = Just "fa fa-trash"
                , title = texts.deleteThisFolder
                , inputClass =
                    [ ( S.deleteButton, True )
                    , ( "hidden", model.folder.id == "" )
                    ]
                }
            ]
        , rootClasses = "mb-4"
        , sticky = True
        }
