{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ >= 800
{-# LANGUAGE TemplateHaskellQuotes #-}
#else
{-# LANGUAGE TemplateHaskell #-}
#endif

module Text.Email.QuasiQuotation
    ( email
    ) where

import qualified Data.ByteString.Char8 as BS8

import Language.Haskell.TH.Quote (QuasiQuoter(..))

import Text.Email.Validate (validate, localPart, domainPart, unsafeEmailAddress)

-- | A QuasiQuoter for email addresses. 
--
-- Use it like this (requires `QuasiQuotes` to be enabled):
-- 
-- >>> [email|someone@example.com|]
-- "someone@example.com"
email :: QuasiQuoter
email :: QuasiQuoter
email = QuasiQuoter
    { quoteExp :: String -> Q Exp
quoteExp = forall {a}. (EmailAddress -> a) -> String -> a
quoteEmail forall {m :: * -> *}. Quote m => EmailAddress -> m Exp
emailToExp
    , quotePat :: String -> Q Pat
quotePat = forall a. HasCallStack => String -> a
error String
"email is not supported as a pattern"
    , quoteDec :: String -> Q [Dec]
quoteDec = forall a. HasCallStack => String -> a
error String
"email is not supported at top-level"
    , quoteType :: String -> Q Type
quoteType = forall a. HasCallStack => String -> a
error String
"email is not supported as a type"
    }
    where

    quoteEmail :: (EmailAddress -> a) -> String -> a
quoteEmail EmailAddress -> a
p String
s = 
        case ByteString -> Either String EmailAddress
validate (String -> ByteString
BS8.pack String
s) of 
            Left String
err -> forall a. HasCallStack => String -> a
error (String
"Invalid quasi-quoted email address: " forall a. [a] -> [a] -> [a]
++ String
err) 
            Right EmailAddress
e -> EmailAddress -> a
p EmailAddress
e

    emailToExp :: EmailAddress -> m Exp
emailToExp EmailAddress
e = 
        let lp :: String
lp = ByteString -> String
BS8.unpack (EmailAddress -> ByteString
localPart EmailAddress
e) in
        let dp :: String
dp = ByteString -> String
BS8.unpack (EmailAddress -> ByteString
domainPart EmailAddress
e) in
        [| unsafeEmailAddress (BS8.pack lp) (BS8.pack dp) |]