module ServantSerf.Module where

import qualified Data.List as List
import qualified Data.Maybe as Maybe
import qualified ServantSerf.Type.Config as Config
import qualified ServantSerf.Type.Context as Context
import qualified ServantSerf.Type.ModuleName as ModuleName
import qualified System.FilePath as FilePath

generate :: Context.Context -> [FilePath] -> String
generate :: Context -> [String] -> String
generate Context
context [String]
files =
  let source :: String
source = Context -> String
Context.source Context
context
      config :: Config
config = Context -> Config
Context.config Context
context
      apiName :: String
apiName = Config -> String
Config.apiName Config
config
      serverName :: String
serverName = Config -> String
Config.serverName Config
config
      moduleName :: String
moduleName = case Config -> Maybe ModuleName
Config.moduleName Config
config of
        Maybe ModuleName
Nothing ->
          String -> (ModuleName -> String) -> Maybe ModuleName -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"Main" ModuleName -> String
ModuleName.toString
            (Maybe ModuleName -> String)
-> (String -> Maybe ModuleName) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe ModuleName
ModuleName.fromFilePath
            (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Context -> String
Context.source Context
context
        Just ModuleName
x -> ModuleName -> String
ModuleName.toString ModuleName
x
      suffix :: String
suffix = Config -> String
Config.excludeSuffix Config
config
      moduleNames :: [String]
moduleNames =
        (if String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
suffix then [String] -> [String]
forall a. a -> a
id else (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter ((String -> Bool) -> [String] -> [String])
-> (String -> Bool) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
List.isSuffixOf String
suffix)
          ([String] -> [String])
-> ([String] -> [String]) -> [String] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ModuleName -> String) -> [ModuleName] -> [String]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ModuleName -> String
ModuleName.toString
          ([ModuleName] -> [String])
-> ([String] -> [ModuleName]) -> [String] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ModuleName] -> [ModuleName]
forall a. Ord a => [a] -> [a]
List.sort
          ([ModuleName] -> [ModuleName])
-> ([String] -> [ModuleName]) -> [String] -> [ModuleName]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Maybe ModuleName) -> [String] -> [ModuleName]
forall a b. (a -> Maybe b) -> [a] -> [b]
Maybe.mapMaybe String -> Maybe ModuleName
ModuleName.fromFilePath
          ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter (String -> String -> Bool
FilePath.isExtensionOf String
"hs") [String]
files
   in [String] -> String
unlines
        [ String
"{-# LINE 1 " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
forall a. Show a => a -> String
show String
source String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" #-}",
          String
"{-# OPTIONS_GHC -w #-}",
          String
"",
          String
"module " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
moduleName String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" where",
          String
"",
          String
"import qualified Servant",
          String
"",
          String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
List.intercalate String
"\n" ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String
"import qualified " String -> String -> String
forall a. Semigroup a => a -> a -> a
<>) [String]
moduleNames,
          String
"",
          String
"type " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
apiName,
          String
"\t= "
            String -> String -> String
forall a. Semigroup a => a -> a -> a
<> if [String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
moduleNames
              then String
"Servant.EmptyAPI"
              else
                String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
List.intercalate String
"\n\tServant.:<|> " ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
                  (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"." String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
apiName) [String]
moduleNames,
          String
"",
          String
serverName,
          String
"\t= "
            String -> String -> String
forall a. Semigroup a => a -> a -> a
<> if [String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
moduleNames
              then String
"Servant.emptyServer"
              else
                String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
List.intercalate String
"\n\tServant.:<|> " ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
                  (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"." String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
serverName) [String]
moduleNames
        ]