module Panes.Modal.FileInfo exposing
    ( component
    , Model
    , Msg
    , getFileIcon
    )

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, File, FileEntry)
import Lazy exposing (Lazy)
import Network.Messages
import Tools
import PaneMeta exposing (PaneMeta)
import History
import Url
import Iso8601
import Json.Decode as JD

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

type alias Model = 
    { file: Lazy Id File
    , showHistory: Bool
    , play: Maybe Float
    }

type Msg
    = None
    | SendEvent Event
    | ShowHistory Bool
    | SetPlay (Maybe Float)

init : Init Id Model Msg
init _ id =
    triple
        { file = Lazy.Loading id
        , showHistory = False
        , play = Nothing
        }
        Cmd.none
        [ Panes.Send <| Network.Messages.FileFetch id
        ]

view : View Model Msg
view { meta, state } =
    div [ class "modal-file" ]
    <| case state.file of
        Lazy.Loading _ -> [ text "Loading" ]
        Lazy.Loaded file ->
            [ div [ class "modal-file-info-box" ]
                [ div [ class "modal-file-info-icon" ]
                    <| case (getCategory file.mime, meta.info) of
                        ("image", Just info) ->
                            [ Html.img
                                [ HA.src <| "http://localhost:8015/storage/show/" 
                                    ++ Url.percentEncode file.id
                                    ++ "/"
                                    ++ Url.percentEncode file.name
                                    ++ "?key="
                                    ++ Url.percentEncode info.uploadToken
                                , class "modal-file-info-icon-preview"
                                ] []
                            ]
                        _ ->
                            [ Html.img
                                [ HA.src <| getFileIcon file.mime
                                ] []
                            ]
                , viewFileInfo meta file
                ]
            , viewAudioPreview meta file
            , viewLinkList meta state.showHistory file
            , if state.showHistory
                then viewHistory meta file
                else text ""
            ]

viewFileInfo : PaneMeta -> File -> Html Msg
viewFileInfo meta file =
    div [ class "modal-file-info" ]
        [ div [ class "modal-file-info-name" ]
            [ text <| file.name 
            , div [ class "utils-database" ]
                [ text file.database ]
            ]
        , div [ class "modal-file-info-tags" ]
            <| List.filterMap identity
            [ if file.deleted
                then Just <| div [ class "modal-file-info-tag-deleted" ]
                    [ text "deleted" ]
                else Nothing
            , if file.mime == "folder"
                then Just <| div [ class "modal-file-info-tag-folder" ]
                    [ text "folder" ]
                else Nothing
            , if file.confidential
                then Just <| div [ class "modal-file-info-tag-confidential" ]
                    [ text "confidential" ]
                else Nothing
            , if not (List.isEmpty file.entries) 
                    && List.all (\x -> not x.exists) file.entries
                then Just <| div [ class "modal-file-info-tag-not-available" ]
                    [ text "not available" ]
                else Nothing
            ]
        , div [ class "modal-file-info-lines" ]
            <| List.map
                (\(name, value) ->
                    div [ class "modal-file-info-line" ]
                        [ div [ class "modal-file-info-line-name" ]
                            [ text name ]
                        , div [ class "modal-file-info-line-value" ]
                            [ value ]
                        ]
                )
            [ Tuple.pair "created"
                <| Tools.viewDateElement meta.zone meta.now
                    file.created
            , Tuple.pair "modified"
                <| Tools.viewDateElement meta.zone meta.now
                    file.modified
            , Tuple.pair "person"
                <| div 
                    [ class "utils-link"
                    , HE.onClick
                        <| SendEvent
                        <| Panes.Open
                        <| History.Person file.person
                    ]
                    [ text "Open" ]
            ]
        ]

viewLinkList : PaneMeta -> Bool -> File -> Html Msg
viewLinkList meta showHistory file =
    div [ class "modal-file-link-list", class "utils-links" ]
    <| List.filterMap identity
        [ Just <|
            if showHistory
            then Html.a
                [ class "utils-link" 
                , HE.onClick <| ShowHistory False
                ]
                [ text "Hide History" ]
            else Html.a
                [ class "utils-link" 
                , HE.onClick <| ShowHistory True
                ]
                [ text "Show History" ]
        , Maybe.andThen
            (\info ->
                if previewTabSupported file.mime
                then Just <| Html.a
                    [ class "utils-link"
                    , HA.target "_blank"
                    , HA.href
                        <| "http://localhost:8015/storage/show/" 
                        ++ Url.percentEncode file.id
                        ++ "/"
                        ++ Url.percentEncode file.name
                        ++ "?key="
                        ++ Url.percentEncode info.uploadToken
                    ]
                    [ text "Preview" ]
                else Nothing
            )
            meta.info
        , Maybe.map
            (\info -> Html.a
                [ class "utils-link"
                , HA.target "_blank"
                , HA.href 
                    <| "http://localhost:8015/storage/download/" 
                    ++ Url.percentEncode file.id
                    ++ "/"
                    ++ Url.percentEncode file.name
                    ++ "?key="
                    ++ Url.percentEncode info.uploadToken
                ]
                [ text "Download" ]
            )
            meta.info
        ]

viewHistory : PaneMeta -> File -> Html Msg
viewHistory meta file =
    Maybe.map .uploadToken meta.info
    |> \token ->
        div [ class "modal-file-history" ]
        <| List.map
            (\entry ->
                div [ class "modal-file-history-entry" ]
                    [ div [ class "modal-file-history-date" ]
                        [ Tools.viewDateElement meta.zone meta.now
                            entry.date
                        ]
                    , div [ class "modal-file-history-button" ]
                        <| case (token, entry.exists && previewTabSupported file.mime) of
                            (Just tok, True) ->
                                [ Html.a
                                    [ class "utils-link"
                                    , HA.target "_blank"
                                    , HA.href
                                        <| "http://localhost:8015/storage/show/" 
                                        ++ Url.percentEncode file.id
                                        ++ "/"
                                        ++ Url.percentEncode file.name
                                        ++ "?key="
                                        ++ Url.percentEncode tok
                                        ++ "&date="
                                        ++ Url.percentEncode (Iso8601.fromTime entry.date)
                                    ]
                                    [ text "Preview" ]
                                ]
                            _ -> []
                    , div [ class "modal-file-history-button"]
                        <| case (token, entry.exists) of
                            (Just tok, True) ->
                                [ Html.a
                                    [ class "utils-link"
                                    , HA.target "_blank"
                                    , HA.href
                                        <| "http://localhost:8015/storage/download/" 
                                        ++ Url.percentEncode file.id
                                        ++ "/"
                                        ++ Url.percentEncode file.name
                                        ++ "?key="
                                        ++ Url.percentEncode tok
                                        ++ "&date="
                                        ++ Url.percentEncode (Iso8601.fromTime entry.date)
                                    ]
                                    [ text "Download" ]
                                ]
                            _ -> []
                    ]
            )
        <| file.entries

viewAudioPreview : PaneMeta -> File -> Html Msg
viewAudioPreview meta file =
    if List.member file.mime [ "audio/mpeg", "audio/ogg", "audio/wav" ]
    then case meta.info of
        Nothing -> text ""
        Just info ->
            Html.audio
                [ HA.controls True
                , class "modal-file-info-preview-audio"
                , HE.on "pause"
                    <| JD.succeed <| SetPlay Nothing
                , HE.on "play"
                    <| JD.map (SetPlay << Just)
                    <| JD.at [ "target", "currentTime" ] JD.float
                , HE.on "timeupdate"
                    <| JD.map (SetPlay << Just)
                    <| JD.at [ "target", "currentTime" ] JD.float
                ]
                [ Html.source
                    [ HA.src <| "http://localhost:8015/storage/show/" 
                        ++ Url.percentEncode file.id
                        ++ "/"
                        ++ Url.percentEncode file.name
                        ++ "?key="
                        ++ Url.percentEncode info.uploadToken
                    , HA.type_ file.mime
                    ] []
                ]
    else text ""

getCategory : String -> String
getCategory mime =
    let
        rules : List (String -> String)
        rules =
            [ \mime_ ->
                if String.startsWith "image/" mime_
                then "image"
                else mime_
            , \mime_ ->
                if String.startsWith "audio/" mime_
                then "audio"
                else mime_
            , \mime_ ->
                if String.startsWith "video/" mime_
                then "video"
                else mime_
            ]
        
        applyRules : List (a -> a) -> a -> a
        applyRules r s = List.foldl (\f v -> f v) s r

    in applyRules rules mime

getFileIcon : String -> String
getFileIcon type_ =
    case getCategory type_ of
        "image" -> "/img/svgrepo/essential-set-2/picture-13704.svg"
        "audio" -> "/img/svgrepo/essential-set-2/music-player-126007.svg"
        "video" -> "/img/svgrepo/essential-set-2/video-player-138900.svg"
        "folder" -> "/img/svgrepo/essential-set-2/folder-83983.svg"
        "application/pdf" -> "/img/svgrepo/essential-set-2/newspaper-45559.svg"
        _ -> "/img/svgrepo/essential-set-2/file-138881.svg"

previewTabSupported : String -> Bool
previewTabSupported type_ =
    List.member (getCategory type_)
        [ "image", "application/pdf", "video", "audio"
        ]

title : Title Model
title { state } =
    case state.file of
        Lazy.Loading id -> "Loading file #" ++ id
        Lazy.Loaded file -> 
            (case state.play of
                Nothing -> ""
                Just time -> 
                    let
                        intTime : Int
                        intTime = round time

                        hours : Int
                        hours = intTime // 3600

                        minutes : Int
                        minutes = modBy 60 <| intTime // 60

                        seconds : Int
                        seconds = modBy 60 intTime

                        pad : Int -> String
                        pad n =
                            if n < 10
                            then "0" ++ String.fromInt n
                            else String.fromInt n
                        
                        fullTime : String
                        fullTime =
                            if hours > 0
                            then pad hours ++ ":" ++ pad minutes ++ ":" ++ pad seconds
                            else pad minutes ++ ":" ++ pad seconds
                    in 
                        "🎵 [" ++ fullTime ++ "] "
            )
            ++ "File: " ++ file.name

update : Update Model Msg
update msg { state } =
    case msg of
        None -> triple
            state
            Cmd.none
            []
        SendEvent event -> triple
            state
            Cmd.none
            [ event ]
        ShowHistory mode -> triple
            { state | showHistory = mode }
            Cmd.none
            []
        SetPlay play -> triple
            { state | play = play }
            Cmd.none
            []

apply : Apply Model Msg
apply event { state } =
    case (state.file, event) of
        (Lazy.Loading id1, Network.Messages.FileSend id2 (Just file)) ->
            if id1 == id2
            then triple
                { state | file = Lazy.Loaded file }
                Cmd.none
                []
            else triple state Cmd.none []
        (Lazy.Loaded { id }, Network.Messages.FileSend id2 (Just file)) ->
            if id == id2
            then triple
                { state | file = Lazy.Loaded file }
                Cmd.none
                []
            else triple state Cmd.none []
        _ -> triple state Cmd.none []

save : Save Model
save _ = []

subscription : Subscription Model Msg
subscription _ = Sub.none
