{-
The DictProcessor module is responsible for processing
the dictionary that valid words are derived from. 
-}

module DictProcessor where

import           Hangman(isPlayableLetter)
import           Data.Maybe
import           Data.Char
import           Types
import           System.Random (randomRIO)
import           Data.List.Split(chunksOf)
import           Control.Parallel.Strategies(rdeepseq, parMap)

-- Load the dictionary of words
loadWordList :: Int -> FilePath -> IO [Types.Word]
loadWordList wordsLength = fmap processWords . readFile
  where processWords fileStr = concat $ parMap rdeepseq maybeWords (chunksOf 100 (lines fileStr))
        word w
          | length w == wordsLength && (and $ map isPlayableLetter w) = Just (Word $ map toLower w)
          | otherwise = Nothing
        maybeWords wordList = mapMaybe word wordList

-- Select random words from the dictionary of words
getRandomWords :: [Types.Word] -> Int -> IO [Types.Word]
getRandomWords dict n = do indices <- randomDictIndices n (length dict)
                           return $ collectWords dict 0 indices
    where collectWords [] _ _ = []
          collectWords (x:xs) index indices
            | elem index indices = getWord index indices x ++ collectWords xs (succ index) indices
            | otherwise = collectWords xs (succ index) indices
          getWord _ [] _ = []
          getWord a (x:xs) p
            | a == x = p : getWord a xs p
            | otherwise = getWord a xs p

-- Generates a random set of indicies in the list of valid words to determine
--   which words to use in each Hangman game being simulated.
randomDictIndices :: Int -> Int -> IO [Int]
randomDictIndices n dictLength = do 
  randomIndex <- randomRIO (0, dictLength - 1)
  case n <= 1 of
    True -> return [randomIndex]
    _ -> do randomIndices <- randomDictIndices (pred n) dictLength
            return $ randomIndex : randomIndices