module GameList exposing (..) import Dict exposing (Dict) import Duration import Element exposing (Element) import Element.Background import Element.Events import Games.TicTacToe as TicTacToe exposing (TicTacToe) import Layout import Match exposing (Match) import Material.Icons as Icons import Pixels exposing (Pixels) import Quantity exposing (Quantity) import Theme -- MODEL type CreateGameType = CreateTicTacToe type Game = GameTicTacToe String (Match TicTacToe) type GameList = GameList { ticTacToe : Dict String (Match TicTacToe) } type Msg = AddTicTacToe { baseUrl : String, matchId : String } | OnTicTacToe String (Match.Msg TicTacToe) init : {} -> ( GameList, Cmd Msg ) init _ = ( GameList { ticTacToe = Dict.empty } , Cmd.none ) -- UPDATE update : Msg -> GameList -> ( GameList, Cmd Msg ) update msg ((GameList data) as model) = case msg of AddTicTacToe newGame -> let ( newMdl, newM ) = Match.init { autoScroll = Just (Duration.seconds 0.75) , baseUrl = newGame.baseUrl , decoder = TicTacToe.decoder , empty = TicTacToe.empty , matchId = newGame.matchId } in ( GameList { data | ticTacToe = Dict.insert newGame.matchId newMdl data.ticTacToe } , Cmd.map (OnTicTacToe newGame.matchId) newM ) OnTicTacToe key m -> case Dict.get key data.ticTacToe of Nothing -> ( model, Cmd.none ) Just mdl -> case Match.update m mdl of ( newMdl, newM ) -> ( GameList { data | ticTacToe = Dict.insert key newMdl data.ticTacToe } , Cmd.map (OnTicTacToe key) newM ) -- SUBSCRIPTIONS subscriptions : GameList -> Sub Msg subscriptions (GameList data) = Sub.batch [ Dict.toList data.ticTacToe |> List.map (\( key, mdl ) -> Sub.map (OnTicTacToe key) (Match.subscriptions mdl) ) |> Sub.batch ] -- VIEW createGameToString : CreateGameType -> String createGameToString cg = case cg of CreateTicTacToe -> "tic-tac-toe" viewCreateGame : { baseUrl : String , flavor : Theme.Flavor , height : Quantity Int Pixels , onBaseUrl : String -> msg , onPlayers : List String -> msg , players : List String , width : Quantity Int Pixels } -> Element msg viewCreateGame data = Element.none viewGame : { flavor : Theme.Flavor , game : Game , height : Quantity Int Pixels , onNavigateBack : msg , toMsg : Msg -> msg , width : Quantity Int Pixels } -> Element msg viewGame data = let navBarHeight = Pixels.pixels 200 showNavBar = Quantity.ratio (Quantity.toFloatQuantity data.height) navBarHeight <= 3 gameHeight = if showNavBar then data.height |> Quantity.minus navBarHeight else data.height in Element.column [ Element.height <| Element.px <| Pixels.inPixels data.height , Element.width <| Element.px <| Pixels.inPixels data.width ] [ if showNavBar then Element.row [ Element.Background.color (Theme.blueUI data.flavor) , Element.height <| Element.px <| Pixels.inPixels navBarHeight , Element.width <| Element.px <| Pixels.inPixels data.width ] [ Layout.iconAsElement { color = Theme.blue data.flavor , height = Pixels.inPixels navBarHeight , icon = Icons.arrow_back , width = Pixels.inPixels data.width } |> Element.el [ Element.Events.onClick data.onNavigateBack ] ] else Element.none , viewMatch { flavor = data.flavor , game = data.game , height = gameHeight , width = data.width } |> Element.map data.toMsg ] viewMatch : { flavor : Theme.Flavor , game : Game , height : Quantity Int Pixels , width : Quantity Int Pixels } -> Element Msg viewMatch data = case data.game of GameTicTacToe key match -> Match.view { flavor = data.flavor , height = data.height , match = match , toMsg = OnTicTacToe key , viewGame = TicTacToe.view , width = data.width } viewSelection : { flavor : Theme.Flavor , height : Quantity Int Pixels , model : GameList , onCreateGame : msg , onNavigateToGame : Game -> msg , width : Quantity Int Pixels } -> Element msg viewSelection data = case data.model of GameList model -> [ Layout.itemWithSubtext { color = Theme.mantle data.flavor , leftIcon = always Element.none , onPress = Just data.onCreateGame , rightIcon = always Element.none , text = "Create new game" , title = "CREATE" } [] |> List.singleton , model.ticTacToe |> Dict.toList |> List.map (\( key, match ) -> Match.viewListItem { flavor = data.flavor , height = Pixels.pixels 80 , match = match , onPress = Just <| data.onNavigateToGame <| GameTicTacToe key match , width = data.width } ) ] |> List.concat |> Element.column [ Element.centerX ]