{-# LANGUAGE TemplateHaskell #-}

import Memory
import Thought

import Control.Arrow
import Control.Category
import Control.Lens
import Data.Char
import Data.Maybe
import Prelude hiding ((.), id)
import System.Random

getLoop :: Thought IO String (Maybe String) -> IO ()
getLoop thought = do
    (nextVal, newThought) <- getLine >>= stepThought thought
    case nextVal of
        Just s -> putStrLn s >> getLoop newThought
        Nothing -> return ()

data Play = Rock | Paper | Scissors
    deriving (Eq,Show,Ord,Enum)

data Result = Win | Draw | Loss 
    deriving (Eq,Show,Ord,Bounded,Enum)


data World = World {
      _humanWins :: Integer
    , _aiWins :: Integer
    , _gen :: StdGen
    , _lastResult :: Result
    } deriving (Show)
makeLenses ''World

playResult :: Play -> Play -> Result
playResult Rock Paper = Loss
playResult Paper Scissors = Loss
playResult Scissors Rock = Loss
playResult a b
    | a == b = Draw
    | otherwise = Win

choosePlay :: String -> Maybe Play
choosePlay s
     | map toLower s == "rock"     = Just Rock
     | map toLower s == "paper"    = Just Paper
     | map toLower s == "scissors" = Just Scissors
     | otherwise                   =  Nothing

handleGame :: Play -> World -> World
handleGame hP s = lastResult .~ res $ gen .~ newGen $ case res of
        Win -> s & humanWins +~ 1 
        Loss -> s & aiWins +~ 1
        Draw -> s 
    where (newPlay,newGen) = over _1 toEnum $ 
                randomR (0,2) $ view gen s
          res = playResult hP newPlay

logic :: Memory World String
logic = filterInput (isJust . choosePlay) $
    updateWithInput (\i -> handleGame (fromJust $ choosePlay i))

startWorld = World 0 0 <$> newStdGen <*> pure undefined

main = do
    sw <- startWorld
    getLoop $ think logic sw >>> arr (Just . show)
