module Shared exposing
    ( Flags, decoder
    , Model, Msg
    , init, update, subscriptions
    )

{-|

@docs Flags, decoder
@docs Model, Msg
@docs init, update, subscriptions

-}

import Browser.Events as BR exposing (..)
import Config.Data.Language as TyLang
import Dict
import Effect exposing (Effect, none)
import Element as E exposing (..)
import Json.Decode exposing (..)
import Route exposing (Route)
import Route.Path
import Shared.Model exposing (..)
import Shared.Msg



-- FLAGS


type alias Flags =
    { height : Int
    , user : Maybe Shared.Model.User
    , width : Int
    }


decoder : Json.Decode.Decoder Flags
decoder =
    Json.Decode.map3
        (\height user width ->
            { height = height
            , user = user
            , width = width
            }
        )
        (field "height" int)
        (field "user" (Json.Decode.maybe userDecoder))
        (field "width" int)


userDecoder : Json.Decode.Decoder Shared.Model.User
userDecoder =
    Json.Decode.map2 Shared.Model.User
        (Json.Decode.field "token" Json.Decode.string)
        (Json.Decode.field "name" Json.Decode.string)



-- INIT


type alias Model =
    Shared.Model.Model


init : Result Json.Decode.Error Flags -> Route () -> ( Model, Effect Msg )
init flagsResult route =
    ( modelFromFlagsResult flagsResult
    , Effect.none
    )


modelFromFlagsResult : Result Error Flags -> Model
modelFromFlagsResult f =
    case f of
        Ok flags ->
            { device = classifyDevice flags
            , height = flags.height
            , isNavbarExpanded = False
            , language = TyLang.English
            , user = Just { token = "asht", name = "billy" }
            , width = flags.width
            , isPopUpClicked = False
            }

        Err e ->
            { device =
                classifyDevice
                    { height = 0
                    , width = 0
                    }
            , height = 10
            , isNavbarExpanded = False
            , language = TyLang.English
            , user = Nothing
            , width = 10
            , isPopUpClicked = False
            }



-- UPDATE


type alias Msg =
    Shared.Msg.Msg


update : Route () -> Msg -> Model -> ( Model, Effect Msg )
update route msg model =
    case msg of
        Shared.Msg.Resize width height ->
            ( { model
                | device =
                    { height = height
                    , width = width
                    }
                        |> E.classifyDevice
                , height = height
                , width = width
              }
            , Effect.none
            )

        Shared.Msg.ToggleNavbarExpansion ->
            ( { model | isNavbarExpanded = not model.isNavbarExpanded }
            , Effect.none
            )

        Shared.Msg.TogglePopUp ->
            ( { model | isPopUpClicked = not model.isPopUpClicked }
            , Effect.none
            )

        Shared.Msg.SignIn user ->
            ( { model | user = Just user }
            , Effect.batch
                [ Effect.pushRoute
                    { path =
                        Dict.get "from" route.query
                            |> Maybe.andThen Route.Path.fromString
                            |> Maybe.withDefault Route.Path.Contact
                    , query = Dict.empty
                    , hash = Nothing
                    }
                , Effect.saveUser user
                ]
            )

        Shared.Msg.SignOut ->
            ( { model | user = Nothing }
            , Effect.clearUser
            )

        Shared.Msg.ToggleLanguage ->
            ( { model
                | language =
                    case model.language of
                        TyLang.Bulgarian ->
                            TyLang.Chinese

                        TyLang.Chinese ->
                            TyLang.Czech

                        TyLang.Czech ->
                            TyLang.Danish

                        TyLang.Danish ->
                            TyLang.Dutch

                        TyLang.Dutch ->
                            TyLang.English

                        TyLang.English ->
                            TyLang.Estonian

                        TyLang.Estonian ->
                            TyLang.Finnish

                        TyLang.Finnish ->
                            TyLang.French

                        TyLang.French ->
                            TyLang.German

                        TyLang.German ->
                            TyLang.Greek

                        TyLang.Greek ->
                            TyLang.Hungarian

                        TyLang.Hungarian ->
                            TyLang.Indonesian

                        TyLang.Indonesian ->
                            TyLang.Italian

                        TyLang.Italian ->
                            TyLang.Japanese

                        TyLang.Japanese ->
                            TyLang.Korean

                        TyLang.Korean ->
                            TyLang.Latvian

                        TyLang.Latvian ->
                            TyLang.Lithuanian

                        TyLang.Lithuanian ->
                            TyLang.Norwegian

                        TyLang.Norwegian ->
                            TyLang.Polish

                        TyLang.Polish ->
                            TyLang.Portuguese

                        TyLang.Portuguese ->
                            TyLang.Romanian

                        TyLang.Romanian ->
                            TyLang.Russian

                        TyLang.Russian ->
                            TyLang.Slovak

                        TyLang.Slovak ->
                            TyLang.Slovenian

                        TyLang.Slovenian ->
                            TyLang.Spanish

                        TyLang.Spanish ->
                            TyLang.Swedish

                        TyLang.Swedish ->
                            TyLang.Turkish

                        TyLang.Turkish ->
                            TyLang.Ukranian

                        TyLang.Ukranian ->
                            TyLang.Bulgarian
              }
            , Effect.none
            )



-- SUBSCRIPTIONS


subscriptions : Route () -> Model -> Sub Msg
subscriptions route model =
    BR.onResize Shared.Msg.Resize
