{-# LANGUAGE LambdaCase #-}

{-|
Module:      Boardgame.Web
Description: Functions that interact with a JavaScript runtime through WASM.

This module is useful if you wish to create web UI through the use of
<https://webassembly.org/ WebAssembly> and regular web technologies.

Our complementary <https://github.com/Boardgame-DSL/boardgame.js#boardgamejs boardgame.js>
JavaScript library can be useful as it contains the necessary JavaScript
functions and some extra helper functions.

= Usage example

== Simple
Imagine a 'Boardgame.PositionalGame' called @TicTacToe@, with a function
@newTicTacToe@ that instantiates it. If you wish to build a web UI for the
game, you can use the default way of exposing the Haskell model to the
JavaScript runtime:

> main = defaultWebGame newTicTacToe

After that, the game can be started form the JavaScript runtime with the
function @window.boardgame.games.default()@.

== Multiple games
If you also have another game, say @Hex@ with a function @newHex@. And you want
to play both from the same UI you can instead use the following method.

> main = do
>   addWebGame "TicTacToe" newTicTacToe
>   addWebGame "Hex" newHex
>   webReady

With this, the JavaScript runtime can access both games through the
@window.boardgame.games@ object. @window.boardgame.games.TicTacToe()@ and
@window.boardgame.games.Hex()@ respectively.

The 'webReady' call is used to invoke the @window.boardgame.initialized@ event.

= Remember
Compile with <https://github.com/tweag/asterius/ Asterius> and the @wasm@ flag
active.

> ahc-cabal new-build --flags="wasm"
-}
module Boardgame.Web (
    playWeb
  , defaultWebGame
  , addWebGame
  , webReady
) where

import Data.Aeson (FromJSON, ToJSON)
import Data.Functor ((<&>))
import Boardgame (
    Player(..)
  , PositionalGame(..)
  , playerToInt
  , play
  )

-- | A main function for running games as a web app. Initializes the provided
--   game as "default" and "tells" JavaScript it's ready. Then JavaScript can
--   start games whenever.
defaultWebGame :: (ToJSON a, ToJSON c, FromJSON c, PositionalGame a c) => a -> IO ()
defaultWebGame startState = undefined

-- | Adds a named game to the list of games accessible from JavaScript.
addWebGame :: (ToJSON a, ToJSON c, FromJSON c, PositionalGame a c) => String -> a -> IO ()
addWebGame name startState = undefined

-- | Lets JavaScript know that the Haskell backend is up and running by firing
--   the ready event.
webReady :: IO ()
webReady = undefined

-- | Plays a 'PositionalGame' with the help of JavaScript FFI. The state of the
--   game ('a') needs to implement 'Data.Aeson.ToJSON' and the coordinates
--   ('c') needs to implement 'Data.Aeson.FromJSON'. This is because they need
--   to be passed to and from (respectively) the JavaScript runtime.
playWeb :: (ToJSON a, ToJSON c, FromJSON c, PositionalGame a c) => a -> IO ()
playWeb = undefined