content: module Lib
    ( Alphabet,
      loremIpsum,
      lowerAlphabet,
      upperAlphabet,
      digits,
      isLower,
      isUpper,
      isDigit,
      isMisc,
      indexOf,
      alphabetRot,
      upperRot,
      lowerRot,
      rotChar,
      caesar,
      rot13,
    )
  where
  
  type Alphabet = [Char]
  
  -- This string can be used for testing!
  loremIpsum :: String
  loremIpsum = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
  
  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 n ch = alphabetRot upperAlphabet n ch
  
  lowerRot :: Int -> Char -> Char
  lowerRot n ch = alphabetRot lowerAlphabet n ch
  
  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 message = map (\ch -> rotChar n ch) message
  
  rot13 :: String -> String
  rot13 message = caesar 13 message
  