# LANGUAGE LambdaCase #

module LambdaHeights.Play.Output
  ( output,
    writeDescription,
    createDescription,
  )
where

import qualified ComposeEngine.Types.Loop as Loop
import Control.Concurrent.STM.TChan
import Control.Monad.IO.Class
import Control.Monad.STM
import Data.Time
import Data.Yaml
import LambdaHeights.Types.Events
import qualified LambdaHeights.Types.PlayState as State
import qualified LambdaHeights.Types.Player as Player
import qualified LambdaHeights.Types.ReplayState as Replay
import LambdaHeights.Version

type Output = Loop.Output IO State.State State.Result Events

type DescriptionGen = State.Result -> Replay.Description

type DescriptionWriter = State.Result -> IO ()

-- | Outputs occured events into a channel and
--   creates a replay description file if the end is reached.
output :: DescriptionWriter -> TChan (Maybe [PlayerEvent]) -> Output
output descWriter channel events = do
  liftIO $ atomically $ writeTChan channel $ Just (player events)
  Loop.askOutputState >>= \case
    Left result -> liftIO $ do
      atomically $ writeTChan channel Nothing
      descWriter result
    Right _ -> return ()

writeDescription :: FilePath -> DescriptionGen -> DescriptionWriter
writeDescription fileName descGen result = encodeFile (fileName ++ ".desc") $ toJSON (descGen result)

createDescription :: LocalTime -> FilePath -> DescriptionGen
createDescription time fileName result = Replay.Description
  { Replay.fileName = fileName ++ ".dat",
    Replay.time = time,
    Replay.duration = State.duration $ State.state result,
    Replay.score = Player.score $ State.player $ State.state result,
    Replay.version = currentVersion
  }

 | Outputs occured events into a channel and
   creates a replay description file if the end is reached.
# LANGUAGE LambdaCase #

module LambdaHeights.Play.Output
  ( output,
    writeDescription,
    createDescription,
  )
where

import qualified ComposeEngine.Types.Loop as Loop
import Control.Concurrent.STM.TChan
import Control.Monad.IO.Class
import Control.Monad.STM
import Data.Time
import Data.Yaml
import LambdaHeights.Types.Events
import qualified LambdaHeights.Types.PlayState as State
import qualified LambdaHeights.Types.Player as Player
import qualified LambdaHeights.Types.ReplayState as Replay
import LambdaHeights.Version

type Output = Loop.Output IO State.State State.Result Events

type DescriptionGen = State.Result -> Replay.Description

type DescriptionWriter = State.Result -> IO ()

output :: DescriptionWriter -> TChan (Maybe [PlayerEvent]) -> Output
output descWriter channel events = do
  liftIO $ atomically $ writeTChan channel $ Just (player events)
  Loop.askOutputState >>= \case
    Left result -> liftIO $ do
      atomically $ writeTChan channel Nothing
      descWriter result
    Right _ -> return ()

writeDescription :: FilePath -> DescriptionGen -> DescriptionWriter
writeDescription fileName descGen result = encodeFile (fileName ++ ".desc") $ toJSON (descGen result)

createDescription :: LocalTime -> FilePath -> DescriptionGen
createDescription time fileName result = Replay.Description
  { Replay.fileName = fileName ++ ".dat",
    Replay.time = time,
    Replay.duration = State.duration $ State.state result,
    Replay.score = Player.score $ State.player $ State.state result,
    Replay.version = currentVersion
  }
