{-# 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 :: String -> (String, String)
moduleDirFile String
mname =
  let splitted :: [String]
splitted = forall a. Eq a => [a] -> [a] -> [[a]]
splitOn String
"." String
mname
      moddir :: String
moddir = forall a. [a] -> [[a]] -> [a]
intercalate String
"/" (forall a. [a] -> [a]
init [String]
splitted)
      modfile :: String
modfile = (forall a. [a] -> a
last [String]
splitted) forall a. Semigroup a => a -> a -> a
<> String
".hs"
   in (String
moddir, String
modfile)

hline :: IO ()
hline :: IO ()
hline = String -> IO ()
putStrLn String
"--------------------------------------------------------"

toUppers :: String -> String
toUppers :: String -> String
toUppers = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper

toLowers :: String -> String
toLowers :: String -> String
toLowers = forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower

firstLower :: String -> String
firstLower :: String -> String
firstLower [] = []
firstLower (Char
x : String
xs) = (Char -> Char
toLower Char
x) forall a. a -> [a] -> [a]
: String
xs

firstUpper :: String -> String
firstUpper :: String -> String
firstUpper [] = []
firstUpper (Char
x : String
xs) = (Char -> Char
toUpper Char
x) forall a. a -> [a] -> [a]
: String
xs

conn :: String -> String -> String -> String
conn :: String -> String -> String -> String
conn String
st String
x String
y = String
x forall a. Semigroup a => a -> a -> a
<> String
st forall a. Semigroup a => a -> a -> a
<> String
y

connspace :: String -> String -> String
connspace :: String -> String -> String
connspace = String -> String -> String -> String
conn String
" "

conncomma :: String -> String -> String
conncomma :: String -> String -> String
conncomma = String -> String -> String -> String
conn String
", "

connBSlash :: String -> String -> String
connBSlash :: String -> String -> String
connBSlash = String -> String -> String -> String
conn String
"\\\n"

connSemicolonBSlash :: String -> String -> String
connSemicolonBSlash :: String -> String -> String
connSemicolonBSlash = String -> String -> String -> String
conn String
"; \\\n"

connRet :: String -> String -> String
connRet :: String -> String -> String
connRet = String -> String -> String -> String
conn String
"\n"

connRet2 :: String -> String -> String
connRet2 :: String -> String -> String
connRet2 = String -> String -> String -> String
conn String
"\n\n"

connArrow :: String -> String -> String
connArrow :: String -> String -> String
connArrow = String -> String -> String -> String
conn String
" -> "

intercalateWith :: (String -> String -> String) -> (a -> String) -> [a] -> String
intercalateWith :: forall a.
(String -> String -> String) -> (a -> String) -> [a] -> String
intercalateWith String -> String -> String
f a -> String
mapper [a]
x
  | Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [a]
x) = forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 String -> String -> String
f (forall a b. (a -> b) -> [a] -> [b]
map a -> String
mapper [a]
x)
  | Bool
otherwise = String
""

intercalateWithM :: (Monad m) => (String -> String -> String) -> (a -> m String) -> [a] -> m String
intercalateWithM :: forall (m :: * -> *) a.
Monad m =>
(String -> String -> String) -> (a -> m String) -> [a] -> m String
intercalateWithM String -> String -> String
f a -> m String
mapper [a]
x
  | Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [a]
x) = do
    [String]
ms <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM a -> m String
mapper [a]
x
    forall (m :: * -> *) a. Monad m => a -> m a
return (forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 String -> String -> String
f [String]
ms)
  | Bool
otherwise = forall (m :: * -> *) a. Monad m => a -> m a
return String
""

-- TODO: deprecate this and use contextT
context :: [(Text, String)] -> Context
context :: [(Text, String)] -> Context
context [(Text, String)]
assocs Text
x = forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall {a}. a
err (String -> Text
T.pack) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Text
x forall a b. (a -> b) -> a -> b
$ [(Text, String)]
assocs
  where
    err :: a
err = forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ String
"Could not find key: " forall a. Semigroup a => a -> a -> a
<> (Text -> String
T.unpack Text
x)

-- TODO: Rename this to context.
-- TODO: Proper error handling.
contextT :: [(Text, Text)] -> Context
contextT :: [(Text, Text)] -> Context
contextT [(Text, Text)]
assocs Text
x = forall a. a -> Maybe a -> a
fromMaybe forall {a}. a
err forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Text
x forall a b. (a -> b) -> a -> b
$ [(Text, Text)]
assocs
  where
    err :: a
err = forall a. HasCallStack => String -> a
error forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack (Text
"Could not find key: " forall a. Semigroup a => a -> a -> a
<> Text
x)

subst :: Text -> Context -> String
subst :: Text -> Context -> String
subst Text
t Context
c = Text -> String
TL.unpack (Text -> Context -> Text
substitute Text
t Context
c)