{-|
Module      : Gargantext.Core.Config.Mail
Description :
Copyright   : (c) CNRS, 2017-Present
License     : AGPL + CECILL v3
Maintainer  : team@gargantext.org
Stability   : experimental
Portability : POSIX

-}

{-# LANGUAGE TemplateHaskell #-}

module Gargantext.Core.Config.Mail (
  -- * Types
    GargMail(..)
  , LoginType(..)
  , MailConfig(..)

  -- * Utility functions
  , gargMail
  , readConfig

  -- * Lenses
  , mc_mail_from
  , mc_mail_host
  , mc_mail_login_type
  , mc_mail_password
  , mc_mail_port
  , mc_mail_user
  )
  where

import Data.Maybe
import Data.Text (unpack)
import Data.Text qualified as T
import Gargantext.Core.Config (readIniFile', val)
import Gargantext.Prelude
import Network.Mail.Mime (plainPart)
import Network.Mail.SMTP hiding (htmlPart, STARTTLS)
import Network.Socket (PortNumber)
import Prelude (read)


type Email = Text
type Name  = Text

data LoginType = NoAuth | Normal | SSL | TLS | STARTTLS
  deriving (Generic, Eq, Show, Read)

data MailConfig = MailConfig { _mc_mail_host         :: !T.Text
                             , _mc_mail_port         :: !PortNumber
                             , _mc_mail_user         :: !T.Text
                             , _mc_mail_password     :: !T.Text
                             , _mc_mail_login_type   :: !LoginType
                             , _mc_mail_from         :: !T.Text
                             }
  deriving (Generic, Show)

readConfig :: FilePath -> IO MailConfig
readConfig fp = do
  ini <- readIniFile' fp
  let val' = val ini "mail"

  pure $ MailConfig { _mc_mail_host       =        cs $ val' "MAIL_HOST"
                    , _mc_mail_port       = read $ cs $ val' "MAIL_PORT"
                    , _mc_mail_user       =        cs $ val' "MAIL_USER"
                    , _mc_mail_from       =        cs $ val' "MAIL_FROM"
                    , _mc_mail_password   =        cs $ val' "MAIL_PASSWORD"
                    , _mc_mail_login_type = read $ cs $ val' "MAIL_LOGIN_TYPE"
                    }


data GargMail = GargMail { gm_to      :: Email
                         , gm_name    :: Maybe Name
                         , gm_subject :: Text
                         , gm_body    :: Text
                         }

-- | TODO add parameters to gargantext.ini
gargMail :: MailConfig -> GargMail -> IO ()
gargMail (MailConfig {..}) (GargMail { .. }) = do
  let host     = unpack _mc_mail_host
      user     = unpack _mc_mail_user
      password = unpack _mc_mail_password
  case _mc_mail_login_type of
    NoAuth   -> sendMail                   host mail
    Normal   -> sendMailWithLogin'         host _mc_mail_port user password mail
    SSL      -> sendMailWithLoginTLS'      host _mc_mail_port user password mail
    TLS      -> sendMailWithLoginTLS'      host _mc_mail_port user password mail
    STARTTLS -> sendMailWithLoginSTARTTLS' host _mc_mail_port user password mail
  where
    mail = simpleMail sender receiver cc bcc gm_subject [plainPart $ cs gm_body]

    sender   = Address (Just "GarganText Email") _mc_mail_from
    receiver = [Address gm_name gm_to]
    cc       = []
    bcc      = []

makeLenses ''MailConfig
