module IHP.IDE.CodeGen.MailGenerator (buildPlan, buildPlan', MailConfig (..)) where

import IHP.Prelude
import IHP.IDE.CodeGen.Types
import qualified Data.Text as Text
import qualified IHP.IDE.SchemaDesigner.Parser as SchemaDesigner
import IHP.IDE.SchemaDesigner.Types

data MailConfig = MailConfig
    { MailConfig -> Text
controllerName :: Text
    , MailConfig -> Text
applicationName :: Text
    , MailConfig -> Text
modelName :: Text
    , MailConfig -> Text
mailName :: Text
    } deriving (MailConfig -> MailConfig -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MailConfig -> MailConfig -> Bool
$c/= :: MailConfig -> MailConfig -> Bool
== :: MailConfig -> MailConfig -> Bool
$c== :: MailConfig -> MailConfig -> Bool
Eq, Int -> MailConfig -> ShowS
[MailConfig] -> ShowS
MailConfig -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MailConfig] -> ShowS
$cshowList :: [MailConfig] -> ShowS
show :: MailConfig -> String
$cshow :: MailConfig -> String
showsPrec :: Int -> MailConfig -> ShowS
$cshowsPrec :: Int -> MailConfig -> ShowS
Show)

buildPlan :: Text -> Text -> Text -> IO (Either Text [GeneratorAction])
buildPlan :: Text -> Text -> Text -> IO (Either Text [GeneratorAction])
buildPlan Text
mailName Text
applicationName Text
controllerName' =
    if (forall mono. MonoFoldable mono => mono -> Bool
null Text
mailName Bool -> Bool -> Bool
|| forall mono. MonoFoldable mono => mono -> Bool
null Text
controllerName')
        then forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left Text
"Neither mail name nor controller name can be empty"
        else do
            [Statement]
schema <- IO (Either ByteString [Statement])
SchemaDesigner.parseSchemaSql forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
                Left ByteString
parserError -> forall (f :: * -> *) a. Applicative f => a -> f a
pure []
                Right [Statement]
statements -> forall (f :: * -> *) a. Applicative f => a -> f a
pure [Statement]
statements
            let modelName :: Text
modelName = Text -> Text
tableNameToModelName Text
controllerName'
            let controllerName :: Text
controllerName = Text -> Text
tableNameToControllerName Text
controllerName'
            let viewConfig :: MailConfig
viewConfig = MailConfig { Text
controllerName :: Text
modelName :: Text
applicationName :: Text
mailName :: Text
$sel:mailName:MailConfig :: Text
$sel:modelName:MailConfig :: Text
$sel:applicationName:MailConfig :: Text
$sel:controllerName:MailConfig :: Text
.. }
            forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ [Statement] -> MailConfig -> [GeneratorAction]
buildPlan' [Statement]
schema MailConfig
viewConfig

-- E.g. qualifiedMailModuleName config "Confirmation" == "Web.Mail.Users.Confirmation"
qualifiedViewModuleName :: MailConfig -> Text -> Text
qualifiedViewModuleName :: MailConfig -> Text -> Text
qualifiedViewModuleName MailConfig
config Text
mailName =
    forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get forall a. IsLabel "applicationName" a => a
#applicationName MailConfig
config forall a. Semigroup a => a -> a -> a
<> Text
".Mail." forall a. Semigroup a => a -> a -> a
<> forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get forall a. IsLabel "controllerName" a => a
#controllerName MailConfig
config forall a. Semigroup a => a -> a -> a
<> Text
"." forall a. Semigroup a => a -> a -> a
<> Text -> Text
ucfirst Text
mailName

buildPlan' :: [Statement] -> MailConfig -> [GeneratorAction]
buildPlan' :: [Statement] -> MailConfig -> [GeneratorAction]
buildPlan' [Statement]
schema MailConfig
config =
        let
            controllerName :: Text
controllerName = forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get forall a. IsLabel "controllerName" a => a
#controllerName MailConfig
config
            name :: Text
name = forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get forall a. IsLabel "mailName" a => a
#mailName MailConfig
config
            singularName :: Text
singularName = MailConfig
config forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get forall a. IsLabel "modelName" a => a
#modelName
            singularVariableName :: Text
singularVariableName = Text -> Text
lcfirst Text
singularName
            pluralVariableName :: Text
pluralVariableName = Text -> Text
lcfirst Text
controllerName
            nameWithSuffix :: Text
nameWithSuffix = if Text
"Mail" Text -> Text -> Bool
`isSuffixOf` Text
name
                then Text
name
                else Text
name forall a. Semigroup a => a -> a -> a
<> Text
"Mail" --e.g. "Test" -> "TestMail"
            nameWithoutSuffix :: Text
nameWithoutSuffix = if Text
"Mail" Text -> Text -> Bool
`isSuffixOf` Text
name
                then Text -> Text -> Text -> Text
Text.replace Text
"Mail" Text
"" Text
name
                else Text
name --e.g. "TestMail" -> "Test"

            indexAction :: Text
indexAction = Text -> Text
pluralize Text
singularName forall a. Semigroup a => a -> a -> a
<> Text
"Action"

            modelFields :: [Text]
            modelFields :: [Text]
modelFields = [ Text -> Text
modelNameToTableName Text
pluralVariableName, Text
pluralVariableName ]
                    forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ([Statement] -> Text -> Maybe [Text]
fieldsForTable [Statement]
schema)
                    forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall a. [a] -> Maybe a
head
                    forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> forall a. a -> Maybe a -> a
fromMaybe []

            mail :: Text
mail =
                Text
""
                forall a. Semigroup a => a -> a -> a
<> Text
"module " forall a. Semigroup a => a -> a -> a
<> MailConfig -> Text -> Text
qualifiedViewModuleName MailConfig
config Text
nameWithoutSuffix forall a. Semigroup a => a -> a -> a
<> Text
" where\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"import " forall a. Semigroup a => a -> a -> a
<> forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get forall a. IsLabel "applicationName" a => a
#applicationName MailConfig
config forall a. Semigroup a => a -> a -> a
<> Text
".View.Prelude\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"import IHP.MailPrelude\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"data " forall a. Semigroup a => a -> a -> a
<> Text
nameWithSuffix forall a. Semigroup a => a -> a -> a
<> Text
" = " forall a. Semigroup a => a -> a -> a
<> Text
nameWithSuffix forall a. Semigroup a => a -> a -> a
<> Text
" { " forall a. Semigroup a => a -> a -> a
<> Text
singularVariableName forall a. Semigroup a => a -> a -> a
<> Text
" :: " forall a. Semigroup a => a -> a -> a
<> Text
singularName forall a. Semigroup a => a -> a -> a
<> Text
" }\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"instance BuildMail " forall a. Semigroup a => a -> a -> a
<> Text
nameWithSuffix forall a. Semigroup a => a -> a -> a
<> Text
" where\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"    subject = \"Subject\"\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"    to " forall a. Semigroup a => a -> a -> a
<> Text
nameWithSuffix forall a. Semigroup a => a -> a -> a
<> Text
" { .. } = Address { addressName = Just \"Firstname Lastname\", addressEmail = \"fname.lname@example.com\" }\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"    from = \"hi@example.com\"\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"    html " forall a. Semigroup a => a -> a -> a
<> Text
nameWithSuffix forall a. Semigroup a => a -> a -> a
<> Text
" { .. } = [hsx|\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"        Hello World\n"
                forall a. Semigroup a => a -> a -> a
<> Text
"    |]\n"
        in
            [ EnsureDirectory { $sel:directory:CreateFile :: Text
directory = forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get forall a. IsLabel "applicationName" a => a
#applicationName MailConfig
config forall a. Semigroup a => a -> a -> a
<> Text
"/Mail/" forall a. Semigroup a => a -> a -> a
<> Text
controllerName }
            , CreateFile { $sel:filePath:CreateFile :: Text
filePath = forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get forall a. IsLabel "applicationName" a => a
#applicationName MailConfig
config forall a. Semigroup a => a -> a -> a
<> Text
"/Mail/" forall a. Semigroup a => a -> a -> a
<> Text
controllerName forall a. Semigroup a => a -> a -> a
<> Text
"/" forall a. Semigroup a => a -> a -> a
<> Text
nameWithoutSuffix forall a. Semigroup a => a -> a -> a
<> Text
".hs", $sel:fileContent:CreateFile :: Text
fileContent = Text
mail }
            , AddImport { $sel:filePath:CreateFile :: Text
filePath = forall model (name :: Symbol) value.
(KnownSymbol name, HasField name model value) =>
Proxy name -> model -> value
get forall a. IsLabel "applicationName" a => a
#applicationName MailConfig
config forall a. Semigroup a => a -> a -> a
<> Text
"/Controller/" forall a. Semigroup a => a -> a -> a
<> Text
controllerName forall a. Semigroup a => a -> a -> a
<> Text
".hs", $sel:fileContent:CreateFile :: Text
fileContent = Text
"import " forall a. Semigroup a => a -> a -> a
<> MailConfig -> Text -> Text
qualifiedViewModuleName MailConfig
config Text
nameWithoutSuffix }
            ]