{-# LANGUAGE OverloadedStrings #-}
module Network.IRC.Bot.Part.Dice where

import Control.Monad            (replicateM)
import Control.Monad.Trans      (liftIO)
import Data.ByteString          (ByteString)
import Data.ByteString.Char8    (pack)
import Data.Monoid              ((<>))
import Network.IRC.Bot.Log      (LogLevel(Debug))
import Network.IRC.Bot.BotMonad (BotMonad(..), maybeZero)
import Network.IRC.Bot.Commands (PrivMsg(..), sendCommand, replyTo)
import Network.IRC.Bot.Parsec   (botPrefix, nat, parsecPart)
import System.Random            (randomRIO)
import Text.Parsec              (ParsecT, (<|>), (<?>), char, skipMany1, space, string, try)

dicePart :: (BotMonad m) => m ()
dicePart = parsecPart diceCommand

diceCommand :: (BotMonad m) => ParsecT ByteString () m ()
diceCommand =
    do try $ botPrefix >> string "dice"
       logM Debug "dicePart"
       target <- maybeZero =<< replyTo
       (numDice, numSides, modifier) <- (do
         skipMany1 space
         nd <- nat <|> return 1
         if nd > 100
            then fail "You can not roll more than 100 dice."
            else do
              char 'd'
              ns <- (do n <- nat
                        if n > 0
                         then return n
                         else fail "The dice must have at least 1 side"
                    )
              mod <- (do char '+' >> nat) <|> return 0
              return (nd, ns, mod)) <?> "dice <num-dice>d<num-sides>[+<modifier>]"
       rolls <- liftIO $ replicateM (fromIntegral numDice) $ randomRIO (1, numSides)
       let results = "You rolled " ++ show numDice ++ " " ++ show numSides ++ "-sided dice with a +" ++ show modifier ++ " modifier: " ++ show rolls ++ " => " ++ show (sum (modifier : rolls))
       sendCommand (PrivMsg Nothing [target] (pack results))
    <|> return ()