{-
The Runner module is responsible for simulating numerous games of Hangman
and the general control flow of each game.
-}

module Runner where

import           Control.Monad.Free
import           Hangman
import           Types
import           LetterGuesser
import           DictProcessor
import           Control.Parallel.Strategies(rdeepseq, parMap)
import           Control.DeepSeq(force)

-- Simulate several Hangman games.
simulateGames :: String -> Int -> Int -> IO [String]
simulateGames dictFile wordsLength numberOfGames = do 
  validWords <- loadWordList wordsLength dictFile
  wordsToGuess <- getRandomWords validWords numberOfGames
  return $ force (parMap rdeepseq (setupGame validWords) wordsToGuess)

-- Initialize Hangman game state
setupGame :: [Types.Word] -> Types.Word -> String
setupGame wordList wordBeingGuessed = runGame $ playGame state
  where state = Hangman.createInitialState wordList wordBeingGuessed

-- Run a sinlge game of Hangman
runGame :: HangmanGame a -> String
runGame (Free (PlayerTurn is next)) = do
  let letterGuess = Guess $ selectLetter is
  runGame $ next letterGuess
runGame (Free (GameOver (Win is))) = wordToGuess is
runGame _ = error "Error: Game lost. This should never happen."