{-# 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 = String -> String -> [String]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn String
"." String
mname
      moddir :: String
moddir = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"/" ([String] -> [String]
forall a. HasCallStack => [a] -> [a]
init [String]
splitted)
      modfile :: String
modfile = ([String] -> String
forall a. HasCallStack => [a] -> a
last [String]
splitted) String -> String -> String
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 = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper

toLowers :: String -> String
toLowers :: String -> String
toLowers = (Char -> Char) -> String -> String
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) Char -> String -> String
forall a. a -> [a] -> [a]
: String
xs

firstUpper :: String -> String
firstUpper :: String -> String
firstUpper [] = []
firstUpper (Char
x : String
xs) = (Char -> Char
toUpper Char
x) Char -> String -> String
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 String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
st String -> String -> String
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 ([a] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [a]
x) = (String -> String -> String) -> [String] -> String
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 String -> String -> String
f ((a -> String) -> [a] -> [String]
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 ([a] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [a]
x) = do
    [String]
ms <- (a -> m String) -> [a] -> m [String]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM a -> m String
mapper [a]
x
    String -> m String
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((String -> String -> String) -> [String] -> String
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 String -> String -> String
f [String]
ms)
  | Bool
otherwise = String -> m String
forall a. a -> m a
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 = Text -> (String -> Text) -> Maybe String -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
forall {a}. a
err (String -> Text
T.pack) (Maybe String -> Text)
-> ([(Text, String)] -> Maybe String) -> [(Text, String)] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [(Text, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Text
x ([(Text, String)] -> Text) -> [(Text, String)] -> Text
forall a b. (a -> b) -> a -> b
$ [(Text, String)]
assocs
  where
    err :: a
err = String -> a
forall a. HasCallStack => String -> a
error (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"Could not find key: " String -> String -> String
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 = Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
forall {a}. a
err (Maybe Text -> Text)
-> ([(Text, Text)] -> Maybe Text) -> [(Text, Text)] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [(Text, Text)] -> Maybe Text
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Text
x ([(Text, Text)] -> Text) -> [(Text, Text)] -> Text
forall a b. (a -> b) -> a -> b
$ [(Text, Text)]
assocs
  where
    err :: a
err = String -> a
forall a. HasCallStack => String -> a
error (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack (Text
"Could not find key: " Text -> Context
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)