content: {-# LANGUAGE OverloadedStrings #-}
  
  module FFICXX.Generate.Util where
  
  import Data.Char (toLower, toUpper)
  import Data.List (intercalate)
  import Data.List.Split (splitOn)
  import Data.Maybe (fromMaybe)
  import Data.Text (Text)
  import qualified Data.Text as T
  import qualified Data.Text.Lazy as TL
  import Data.Text.Template
    ( Context,
      substitute,
    )
  
  moduleDirFile :: String -> (String, String)
  moduleDirFile mname =
    let splitted = splitOn "." mname
        moddir = intercalate "/" (init splitted)
        modfile = (last splitted) <> ".hs"
     in (moddir, modfile)
  
  hline :: IO ()
  hline = putStrLn "--------------------------------------------------------"
  
  toUppers :: String -> String
  toUppers = map toUpper
  
  toLowers :: String -> String
  toLowers = map toLower
  
  firstLower :: String -> String
  firstLower [] = []
  firstLower (x : xs) = (toLower x) : xs
  
  firstUpper :: String -> String
  firstUpper [] = []
  firstUpper (x : xs) = (toUpper x) : xs
  
  conn :: String -> String -> String -> String
  conn st x y = x <> st <> y
  
  connspace :: String -> String -> String
  connspace = conn " "
  
  conncomma :: String -> String -> String
  conncomma = conn ", "
  
  connBSlash :: String -> String -> String
  connBSlash = conn "\\\n"
  
  connSemicolonBSlash :: String -> String -> String
  connSemicolonBSlash = conn "; \\\n"
  
  connRet :: String -> String -> String
  connRet = conn "\n"
  
  connRet2 :: String -> String -> String
  connRet2 = conn "\n\n"
  
  connArrow :: String -> String -> String
  connArrow = conn " -> "
  
  intercalateWith :: (String -> String -> String) -> (a -> String) -> [a] -> String
  intercalateWith f mapper x
    | not (null x) = foldl1 f (map mapper x)
    | otherwise = ""
  
  intercalateWithM :: (Monad m) => (String -> String -> String) -> (a -> m String) -> [a] -> m String
  intercalateWithM f mapper x
    | not (null x) = do
        ms <- mapM mapper x
        return (foldl1 f ms)
    | otherwise = return ""
  
  -- TODO: deprecate this and use contextT
  context :: [(Text, String)] -> Context
  context assocs x = maybe err (T.pack) . lookup x $ assocs
    where
      err = error $ "Could not find key: " <> (T.unpack x)
  
  -- TODO: Rename this to context.
  -- TODO: Proper error handling.
  contextT :: [(Text, Text)] -> Context
  contextT assocs x = fromMaybe err . lookup x $ assocs
    where
      err = error $ T.unpack ("Could not find key: " <> x)
  
  subst :: Text -> Context -> String
  subst t c = TL.unpack (substitute t c)
  