import System.Random
import System.IO
import System.Exit
import Control.Monad
import Text.Read
import Data.Maybe

promptAgain :: IO Int
promptAgain = do
  putStrLn "Invalid input - must be a number among 1,2 or 3. Try again."
  playerMove

playerMove :: IO Int
playerMove = do
  putStr "Your choice(1 to 3):"
  number <- getLine
  when (number == "q") $ do
    exitWith ExitSuccess
  let n = readMaybe number :: Maybe Int
  x <- if isNothing n
             then promptAgain
             else let val = read number
                   in if (val > 3 || val < 1)
                      then promptAgain
                      else return val
  return x

computerMove :: IO Int
computerMove = do
  x <- randomRIO (1, 3)
  putStrLn $ "Computer move:" ++ (show x)
  return x

gameLoop :: (IO Int, IO Int) -> IO Int
gameLoop moveorder = loop moveorder 0
  where loop moveorder total = do
        number <- fst moveorder
        let total1 = number + total
        putStrLn $ "Running total:" ++ (show total1)
        if total1 >= 21
           then return 0
           else do
             number <- snd moveorder
             let total2 = number + total1
             putStrLn $ "Running total:" ++ (show total2)
             if total2 >= 21
                then return 1
                else loop moveorder total2

main :: IO ()
main = do
  hSetBuffering stdout $ BlockBuffering $ Just 1
  putStrLn "Enter q to quit at any time"
  x <- randomRIO (0, 1) :: IO Int
  let (moveorder, names) = if x == 0
                 then ((playerMove, computerMove), ("Player", "Computer"))
                 else ((computerMove, playerMove), ("Computer", "Player"))
  when (x == 1) $ do
    putStrLn "Computer will start the game"
  y <- gameLoop moveorder
  when (y == 0) $ do
    putStrLn $ (fst names) ++ " has won the game"
  when (y == 1) $ do
    putStrLn $ (snd names) ++ " has won the game"