module Tools exposing (..)

import Time exposing (Posix, Zone)
import Iso8601 exposing (toTime)
import Html exposing (Html)
import Html.Attributes as HA
import Html.Events as HE
import Json.Decode as JD
import Url exposing (Url)
import Dict exposing (Dict)
import Url.Parser exposing (query)
import Triple exposing (Triple)

viewDate : Zone -> Posix -> String
viewDate zone posix =
    String.concat
        [ String.padLeft 4 '0' 
            <| String.fromInt 
            <| Time.toYear zone posix
        , "-"
        , String.padLeft 2 '0' 
            <| String.fromInt  
            <| case Time.toMonth zone posix of
                Time.Jan -> 1
                Time.Feb -> 2
                Time.Mar -> 3
                Time.Apr -> 4
                Time.May -> 5
                Time.Jun -> 6
                Time.Jul -> 7
                Time.Aug -> 8
                Time.Sep -> 9
                Time.Oct -> 10
                Time.Nov -> 11
                Time.Dec -> 12
        , "-"
        , String.padLeft 2 '0' 
            <| String.fromInt 
            <| Time.toDay zone posix
        ]

viewTime : Zone -> Posix -> String
viewTime zone posix =
    String.concat
        [ String.padLeft 2 '0'
            <| String.fromInt
            <| Time.toHour zone posix
        , ":"
        , String.padLeft 2 '0'
            <| String.fromInt
            <| Time.toMinute zone posix
        ]

viewFullTime : Zone -> Posix -> String
viewFullTime zone posix =
    String.concat
        [ viewTime zone posix
        , ":"
        , String.padLeft 2 '0'
            <| String.fromInt
            <| Time.toSecond zone posix
        ]

viewDateTime : Zone -> Posix -> String
viewDateTime zone time =
    viewDate zone time ++ " " ++ viewFullTime zone time

viewDateNotice : Zone -> Posix -> Posix -> String
viewDateNotice zone now time =
    if abs (Time.posixToMillis now - Time.posixToMillis time) >= 16 * 3600 * 1000
    then viewDate zone time
    else if abs (Time.posixToMillis now - Time.posixToMillis time) >= 60 * 1000
    then viewTime zone time
    else if Time.posixToMillis now >= Time.posixToMillis time
    then 
        (String.fromInt
            <| modBy 60
            <| (\x -> x // 1000)
            <| Time.posixToMillis now - Time.posixToMillis time
        ) ++ " seconds ago"
    else "in " ++
        (String.fromInt
            <| modBy 60 
            <| (\x -> x // 1000)
            <| Time.posixToMillis now - Time.posixToMillis time
        ) ++ " seconds"

viewDateElement : Zone -> Posix -> Posix -> Html msg
viewDateElement zone now time =
    Html.span
        [ HA.title <| viewDateTime zone time
        , HA.class "tools-date-element"
        ]
        [ Html.text <| viewDateNotice zone now time ]


onNotShiftEnter : msg -> Html.Attribute msg
onNotShiftEnter event =
    HE.custom "keydown"
        <| JD.andThen
            (\(code, shift) ->
                if code == 13 && not shift
                then JD.succeed
                    { message = event
                    , stopPropagation = True
                    , preventDefault = True
                    }
                else JD.fail "shift+enter"
            )
        <| JD.map2
            Tuple.pair
            HE.keyCode
        <| JD.field "shiftKey" JD.bool

setQueryToUrl : Dict String String -> Url -> Url
setQueryToUrl query url =
    { url
    | query = Just
        <| String.join "&"
        <| List.map
            (\(k, v) -> Url.percentEncode k ++ "=" ++ Url.percentEncode v)
        <| Dict.toList query
    }

insertCmd : Cmd msg -> Triple a (Cmd msg) b -> Triple a (Cmd msg) b
insertCmd cmd =
    Triple.mapSecond
        (\old -> Cmd.batch [ old, cmd ])

addMs : Int -> Posix -> Posix
addMs offset time =
    Time.millisToPosix <| Time.posixToMillis time + offset
