import Data.Map
import Data.Set
import Data.List
import Data.List.Split
import Control.Parallel.Strategies
import System.Random
import System.Environment(getArgs, getProgName)
import System.Exit(die)
import DictUtil
import SquareDefs
import GenerateGrid

fill_and_check_s :: Map Int (Set [Square]) -> [[Square]] -> [[[Square]]]
fill_and_check_s dict grid = do
                             let grids = fill_crossword dict grid
                             let candidates = Prelude.map transpose grids
                             Prelude.filter (check_crossword dict) candidates

fill_and_check_p :: Map Int (Set [Square]) -> [[Square]] -> [[[Square]]]
fill_and_check_p dict grid = do
                             let f = Prelude.filter (check_crossword dict)
                             let grids = fill_crossword dict grid
                             let m = Prelude.map transpose grids
                             let c = Data.List.Split.chunksOf 50 m
                             let p = parBuffer 100 rseq
                             let sols = Prelude.map f c `using` p
                             concat sols

main :: IO ()
main = do args <- getArgs
          case args of
              [dimS, mS, threshS, dictPath, deterministic, parallel] -> do
                  seed <- case deterministic of
                                "y" -> return $ mkStdGen 15
                                _   -> newStdGen
                  let dim = read dimS :: Int
                  let m = read mS :: Int
                  let thresh = read threshS :: Float
                  let result = generateGrid dim m thresh seed
                  let peeled = maybe [[]] (\x -> x) $ result
                  mapM_ (putStrLn) $ Prelude.map show peeled
                  dictStream <- readFile dictPath
                  let dict = build_dict dictStream
                  filled <- case parallel of
                               "y" -> return $ fill_and_check_p dict peeled
                               _   -> return $ fill_and_check_s dict peeled
                  mapM_ (printGrid) filled
                  let num = show (length filled)
                  putStrLn $ "found " ++ num ++ " ways to fill the given grid"
              _ -> do pn <- getProgName
                      die $ "Usage: "++pn++" <dimension> <min_word_length>\
                                              \ <probability_threshold> \
                                              \ <dict_filepath> \
                                              \ <deterministic> \
                                              \ <parallel>"
