module Handler.Utils.Mail
  ( addRecipientsDB
  , userAddress
  , userMailT
  , addFileDB
  ) where

import Import

import Utils.Lens

import qualified Data.CaseInsensitive as CI

import qualified Data.ByteString.Lazy as LBS

import qualified Data.Conduit.List as C

import System.FilePath (takeBaseName)

import Control.Monad.Trans.State (StateT)


addRecipientsDB :: ( MonadMail m
                   , MonadHandler m
                   , HandlerSite m ~ UniWorX
                   ) => [Filter User] -> m ()
-- ^ @setRecipientId uid@ throws an exception if @uid@ does not refer to an existing user
addRecipientsDB uFilter = runConduit $ transPipe (liftHandlerT . runDB) (selectSource uFilter [Asc UserDisplayName]) .| C.mapM_ addRecipient
  where
    addRecipient (Entity _ User{userEmail, userDisplayName}) = do
      let addr = Address (Just userDisplayName) $ CI.original userEmail
      _mailTo %= flip snoc addr

userAddress :: User -> Address
userAddress User{userEmail, userDisplayName} = Address (Just userDisplayName) $ CI.original userEmail

userMailT :: ( MonadHandler m
             , HandlerSite m ~ UniWorX
             , MonadBaseControl IO m
             , MonadLogger m
             ) => UserId -> MailT m a -> m a
userMailT uid mAct = do
  user@User
    { userMailLanguages
    , userDateTimeFormat
    , userDateFormat
    , userTimeFormat
    } <- liftHandlerT . runDB $ getJust uid
  let
    ctx = MailContext
      { mcLanguages = userMailLanguages
      , mcDateTimeFormat = \case
          SelFormatDateTime -> userDateTimeFormat
          SelFormatDate -> userDateFormat
          SelFormatTime -> userTimeFormat
      }
  mailT ctx $ do
    _mailTo .= pure (userAddress user)
    mAct

addFileDB :: ( MonadMail m
             , MonadHandler m
             , HandlerSite m ~ UniWorX
             ) => FileId -> m MailObjectId
addFileDB fId = do
  File{fileTitle = pack . takeBaseName -> fileName, fileContent = Just fileContent} <- liftHandlerT . runDB $ getJust fId
  addPart $ do
    _partType .= decodeUtf8 (mimeLookup fileName)
    _partEncoding .= Base64
    _partFilename .= Just fileName
    _partContent .= LBS.fromStrict fileContent
    setMailObjectIdCrypto fId :: StateT Part (HandlerT UniWorX IO) MailObjectId
