module Panes.Modal.ManageDatabaseAccess exposing
    ( component
    , Model
    , Msg
    )

import Html exposing (Html, div, text)
import Html.Attributes as HA exposing (class)
import Html.Events as HE
import Triple exposing (triple)
import Panes exposing (..)
import Data exposing (Id)
import Data.Schema exposing (Schema)
import Network.Messages
import PaneMeta exposing (PaneMeta)
import Dict
import Regex
import Url
import Data.Info
import Tools

component : RawComponent String Model Msg
component =
    { init = init
    , view = view
    , title = title
    , update = update
    , apply = apply
    , save = save
    , subscription = subscription
    }

type alias Model =
    { name: String
    , remove: Maybe String
    , masterKey: Maybe String
    }

type Msg
    = None
    | SendEvent Event
    | SetRemove (Maybe String)
    | SetMasterKey (Maybe String)

init : Init String Model Msg
init meta name =
    triple
        { name = name
        , remove = Nothing
        , masterKey = Nothing
        }
        Cmd.none
        []

view : View Model Msg
view { meta, state } =
    case 
        Maybe.map .database meta.info
        |> Maybe.withDefault []
        |> List.filter ((==) state.name << .name)
        |> List.head
    of
        Just info ->
            div [ class "modal-manage-database" ]
            <| case state.masterKey of
                Just key -> viewEditMasterkey info.name key
                Nothing -> viewAccessList meta state info
                    ++ viewAddLogin meta state info
        Nothing -> text "Database not found"

viewEditMasterkey : String -> String -> List (Html Msg)
viewEditMasterkey name key =
    [ Html.h2 [] [ text "Enter Master Key" ]
    , Html.p []
        [ text
            <| "Enter the Master Key for the database here. Any special characters "
            ++ "and upper or lower case are ignored. This key gives you full access to the database "
            ++ "without any authorization. The key is created during creation of the database."
        ]
    , Html.textarea
        [ HA.value key
        , HE.onInput <| SetMasterKey << Just
        ] []
    , div [ class "modal-manage-database-buttons" ]
        [ Html.button 
            [ HE.onClick <| SetMasterKey Nothing ]
            [ text "Cancel" ]
        , Html.button
            [ HE.onClick
                <| SendEvent
                <| Panes.Send
                <| Network.Messages.DatabaseUnlock name
                <| Just key
            ]
            [ text "Unlock" ]
        ]
    ]

viewAccessList : PaneMeta.PaneMeta -> Model -> Data.Info.DbInfo -> List (Html Msg)
viewAccessList meta state info =
    if List.isEmpty info.access
    then
        [ Html.h2 [] [ text "Access List" ]
        , Html.p []
            [ text
                <| "There is no user registered here. Try to add a new one to receive access to "
                ++ "the database."
            ]

        ]
    else
        [ Html.h2 [] [ text "Access List" ]
        , Html.p []
            [ text 
                <| "All of these accounts are eligeble to login. It is allowed that one username is "
                ++ "used twice (the difference can be the password or the used Two-Factor-Key)." 
            ]
        , div [ class "modal-manage-database-list" ] 
            <| List.map
                (\access ->
                    if Just access.userId == state.remove
                    then div [ class "modal-manage-database-access" ]
                        [ Html.img
                            [ HA.src "/img/svgrepo/essential-set-2/garbage-51844.svg" 
                            ] []
                        , div [ class "modal-manage-database-access-name" ]
                            [ text <| "Remove " ++ access.user ++ "?" ]
                        , Html.img
                            [ HA.src "/img/svgrepo/essential-set-2/checked-36346.svg"
                            , class "modal-manage-database-access-button"
                            , HE.onClick <| SendEvent <| Panes.Send
                                <| Network.Messages.DatabaseRemoveUser state.name access.userId
                            ] []
                        , Html.img
                            [ HA.src "/img/svgrepo/essential-set-2/multiply-125993.svg"
                            , class "modal-manage-database-access-button"
                            , HE.onClick <| SetRemove Nothing
                            ] []
                        ]
                    else div [ class "modal-manage-database-access" ]
                        [ Html.img
                            [ HA.src "/img/svgrepo/essential-set-2/id-card-36356.svg" 
                            ] []
                        , if access.fidoDescriptor
                                then Html.img
                                    [ HA.src "/img/svgrepo/essential-set-2/fingerprint-84006.svg"
                                    , HA.title "2 Factor Authentication enabled"
                                    ] []
                                else text ""
                        , div [ class "modal-manage-database-access-name" ]
                            [ text access.user ]
                        , Tools.viewDateElement meta.zone meta.now access.created
                        , Html.img
                            [ HA.src "/img/svgrepo/essential-set-2/garbage-51844.svg"
                            , class "modal-manage-database-access-button"
                            , HE.onClick <| SetRemove <| Just access.userId
                            ] []
                        ]
                )
            <| info.access
        ]

viewAddLogin : PaneMeta.PaneMeta -> Model -> Data.Info.DbInfo -> List (Html Msg)
viewAddLogin meta state info =
    case info.unlocked of
        Nothing ->
            [ Html.h2 [] [ text "Add new Access" ]
            , Html.p []
                [ text 
                    <| "Add new access to the database. Before this can be done the database needs "
                    ++ "to be unlocked. Unlocking a database won't open it."
                ]
            , Html.button 
                [ HE.onClick
                    <| SendEvent
                    <| Panes.Send
                    <| Network.Messages.DatabaseUnlock info.name Nothing
                ]
                [ text "Unlock using Login" ]
            , Html.button
                [ HE.onClick <| SetMasterKey <| Just "" ]
                [ text "Unlock using Master Key" ]
            ]
        Just time ->
            [ Html.h2 [] [ text "Add new Access" ]
            , Html.p []
                [ text "Add new access to the database. The database is currently unlocked."
                , Html.br [] []
                , text "Unlocked at: "
                , Tools.viewDateElement meta.zone meta.now time
                ]
            , Html.button
                [ HE.onClick
                    <| SendEvent
                    <| Panes.EnterRegisterAccount info.name Nothing
                ]
                [ text "Register new credential" ]
            ]

title : Title Model
title { state } =
    "Manage Access: " ++ state.name

update : Update Model Msg
update msg { state } =
    case msg of
        None -> triple
            state
            Cmd.none
            []
        SendEvent event -> triple
            state
            Cmd.none
            [ event ]
        SetRemove remove -> triple
            { state | remove = remove }
            Cmd.none
            []
        SetMasterKey key -> triple
            { state | masterKey = key }
            Cmd.none
            []

apply : Apply Model Msg
apply event { state } =
    case event of
        Network.Messages.InfoSend info ->
            if state.masterKey /= Nothing
                && (info.database
                    |> List.filter ((==) state.name << .name)
                    |> List.filter ((/=) Nothing << .unlocked)
                    |> List.isEmpty
                    |> not
                    )  
            then triple { state | masterKey = Nothing } Cmd.none []
            else triple state Cmd.none []
        _ -> triple state Cmd.none []

save : Save Model
save state =
    [ Panes.Send <| Network.Messages.DatabaseLock state.name ]

subscription : Subscription Model Msg
subscription _ = Sub.none
