content: module Caesar.Caesar
    ( Alphabet,
      lowerAlphabet,
      upperAlphabet,
      digits,
      isLower,
      isUpper,
      isDigit,
      isMisc,
      indexOf,
      alphabetRot,
      upperRot,
      lowerRot,
      rotChar,
      caesar,
      rot13,
    )
  where
  
  type Alphabet = [Char]
  
  lowerAlphabet :: Alphabet
  lowerAlphabet = ['a' .. 'z']
  
  upperAlphabet :: Alphabet
  upperAlphabet = ['A' .. 'Z']
  
  digits :: Alphabet
  digits = ['0' .. '9']
  
  isLower :: Char -> Bool
  isLower char = char `elem` lowerAlphabet
  
  isUpper :: Char -> Bool
  isUpper char = char `elem` upperAlphabet
  
  isDigit :: Char -> Bool
  isDigit char = char `elem` digits
  
  isMisc :: Char -> Bool
  isMisc char = char `notElem` lowerAlphabet ++ upperAlphabet ++ digits
  
  indexOf :: Char -> Alphabet -> Int
  indexOf ch [] = undefined
  indexOf ch (x : xs) = if x == ch then 0 else 1 + indexOf ch xs
  
  alphabetRot :: Alphabet -> Int -> Char -> Char
  alphabetRot alphabet n ch =
    alphabet !! ((indexOf ch alphabet + n) `mod` length alphabet)
  
  upperRot :: Int -> Char -> Char
  upperRot = alphabetRot upperAlphabet
  
  lowerRot :: Int -> Char -> Char
  lowerRot = alphabetRot lowerAlphabet
  
  rotChar :: Int -> Char -> Char
  rotChar n ch
    | isLower ch = lowerRot n ch
    | isUpper ch = upperRot n ch
    | otherwise = ch
  
  caesar :: Int -> String -> String
  caesar n = map $ rotChar n
  
  rot13 :: String -> String
  rot13 = caesar 13
  