module Main exposing (main)

import Browser
import Html exposing (..)
import Html.Attributes exposing (src)
import Http
import Time
import Json.Decode exposing (Decoder, map3, field, string, float)



-- MAIN

main =
  Browser.element
  { init = init
  , update = update
  , subscriptions = subscriptions
  , view = view
  }


-- MODEL

type alias Surprise =
  { diff : Float
  , surprise : String
  , asset : String
  }

type Model
  = Failure
  | Success Surprise


init : () -> (Model, Cmd Msg)
init _ =
  (Success { diff = 0.0, surprise = "", asset = "/static/loading.svg" }, getSurprise)


-- UPDATE

type Msg
  = FetchSurprise Time.Posix
  | GotSurprise (Result Http.Error Surprise)


update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    FetchSurprise _ ->
      (model, getSurprise)

    GotSurprise result ->
      case result of
        Ok surprise ->
          (Success surprise, Cmd.none)

        Err _ ->
          (Failure, Cmd.none)


-- SUBSCRIPTIONS

subscriptions : Model -> Sub Msg
subscriptions model =
  Time.every 1000 FetchSurprise


-- VIEW

view : Model -> Html Msg
view model =
  case model of
    Failure ->
      div [] [ text "Failed to fetch from server." ]

    Success surprise ->
      div [] 
        ( (viewDiff surprise.diff)
          ++ [ img [ src surprise.asset ] [] ]
        )


viewDiff: Float -> List (Html Msg)
viewDiff diff =
  diff
    |> round
    |> max 0
    |> secondsToIntervals
    |> List.filter (\(i, _) -> i /= 0)
    |> List.map formatInterval
    |> List.map (\s -> h2 [] [ text s ])


formatInterval: (Int, String) -> String
formatInterval (n, unit) =
  let
      s =
        (String.fromInt n) ++ " " ++ unit
  in
    if n > 1 then
      s ++ "s"
    else
      s 

secondsToIntervals: Int -> List (Int, String)
secondsToIntervals diff =
  let
      (days, daysRem) = 
        (diff // 86400, modBy 86400 diff)
      (hours, hoursRem) =
        (daysRem // 3600, modBy 3600 daysRem)
      (minutes, seconds) =
        (hoursRem // 60, modBy 60 hoursRem)
  in
    [ (days, "day")
    , (hours, "hour")
    , (minutes, "minute")
    , (seconds, "second")
    ]


-- HTTP

getSurprise : Cmd Msg
getSurprise =
  Http.get
  { url = "/get-surprise.json"
  , expect = Http.expectJson GotSurprise surpriseDecoder
  }


surpriseDecoder : Decoder Surprise
surpriseDecoder =
  map3 Surprise
    (field "diff_seconds" float)
    (field "surprise" string)
    (field "asset" string)

