{-# LANGUAGE OverloadedStrings #-}

module FFICXX.Generate.Util where

import           Data.Char 
import           Data.List
import           Data.List.Split
import           Data.Maybe               (fromMaybe)
import           Data.Monoid              ((<>))
import           Data.Text                (Text)
import qualified Data.Text          as T
import qualified Data.Text.Lazy     as TL
import           Data.Text.Template
--

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. [a] -> [a]
init [String]
splitted )
      modfile :: String
modfile = ([String] -> String
forall a. [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 

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 :: (String -> String -> String) -> (a -> String) -> [a] -> String
intercalateWith  String -> String -> String
f a -> String
mapper [a]
x 
  | Bool -> Bool
not ([a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [a]
x) = (String -> String -> String) -> [String] -> String
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 :: (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 (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)
mapM a -> m String
mapper [a]
x
                      String -> m String
forall (m :: * -> *) a. Monad m => a -> m a
return ((String -> String -> String) -> [String] -> String
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 String -> String -> String
f [String]
ms)
  | Bool
otherwise = String -> m String
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)