{-
The Types module is responsible for defining the many data types used
in the Hangman program.
-}

module Types where

import           Data.Set(Set, fromList)
import           Control.Monad.Free

data InternalState = InternalState {
  wordDict :: [Types.Word], -- dynamic list of words that gets smaller as the program makes guesses
  wordToGuess :: String,
  usedLetters :: Set Char,
  currentWord :: [Maybe Char]
} deriving (Show)

-- Types that determine the current state of the Hangman game
newtype RunningState = RunningState InternalState deriving (Show)
data TerminalState = Win InternalState | Loss InternalState deriving (Show)
data GameState = Terminal TerminalState | Running RunningState deriving (Show)

-- Free Monad to abstract the game loop
data HangmanGameF a =
    PlayerTurn InternalState (Guess -> a)
  | GameOver TerminalState
instance Functor HangmanGameF where
  fmap f (PlayerTurn is g) = PlayerTurn is (f . g)
  fmap _ (GameOver ts)     = GameOver ts
type HangmanGame a = Free HangmanGameF a

newtype Guess = Guess Char

newtype Word = Word String deriving Show
-- Gets the underlying strin of the Word type
getWordString :: Types.Word -> String
getWordString (Word s) = s

alphabet :: [Char]
alphabet = ['a'..'z']

alphabetSet :: Set Char
alphabetSet = fromList ['a'..'z']