content: module Directory.Captcha (getCaptchaStr, matchCaptchaStr) where
  
  import qualified Data.Map.Strict as M
  import Data.Maybe (fromMaybe)
  import qualified Data.Text as T
  import System.Random (randomRIO)
  
  getCaptchaStr :: Int -> String -> IO String
  getCaptchaStr 0 s = pure s
  getCaptchaStr n s = do
    i <- randomRIO (0, length captchaChars - 1)
    let c = captchaChars !! i
    getCaptchaStr (n - 1) (c : s)
    where
      captchaChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  
  matchCaptchaStr :: T.Text -> T.Text -> Bool
  matchCaptchaStr captcha guess = T.length captcha == T.length guess && matchChars (T.zip captcha guess)
    where
      matchChars [] = True
      matchChars ((c, g) : cs) = matchChar c == matchChar g && matchChars cs
      matchChar c = fromMaybe c $ M.lookup c captchaMatches
      captchaMatches =
        M.fromList
          [ ('0', 'O'),
            ('1', 'I'),
            ('c', 'C'),
            ('l', 'I'),
            ('o', 'O'),
            ('p', 'P'),
            ('s', 'S'),
            ('u', 'U'),
            ('v', 'V'),
            ('w', 'W'),
            ('x', 'X'),
            ('z', 'Z')
          ]
  