{-# LANGUAGE CPP #-}
#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 702)
{-# LANGUAGE Safe #-}
#endif
-- |Utility functions for responding to HTTP requests from within an 'Action'.
module Data.IterIO.Http.Support.Responses (
    render
  , redirectTo
  , redirectBack
  , respond404
  , respondStat
) where

import Control.Monad.Trans.State
import qualified Data.ByteString.Char8 as S
import qualified Data.ByteString.Lazy.Char8 as L
import Data.IterIO
import Data.IterIO.Http.Support.Action (Action, ActionState(..), requestHeader)
import Data.IterIO.Http

-- | Responds to the client with an empty @404@ (Not Found) response.
respond404 :: Monad m => Action t b m ()
respond404 = modify $
  \s -> s { actionResp = resp404 $ actionReq s }

-- | Replaces the HTTP status in the current 'HttpResp' with the given
-- 'HttpStatus'.
respondStat :: Monad m => HttpStatus -> Action t b m ()
respondStat status = modify $
  \s -> s { actionResp = (actionResp s) { respStatus = status} }

-- | Responds to the client with a @303@ (Temporary Redirect) response to the given
-- path.
redirectTo :: Monad m
           => String -- ^ The path to redirect to
           -> Action t b m ()
redirectTo path = modify $
  \s -> s { actionResp = resp303 path }

-- | Redirect \"back\" according to the \"referer\" header.
redirectBack :: Monad m => Action t b m ()
redirectBack = do
  mhdr <- requestHeader (S.pack "referer")
  maybe (fail "Referer header not set") (redirectTo . S.unpack) mhdr
  

-- | Responds to the client with a @200@ (Success) response with the given body
-- and mime-type.
render :: Monad m
       => String -- ^ The mime-type of the response (commonly \"text\/html\")
       -> L.ByteString -- ^ The response body
       -> Action t b m ()
render ctype text = modify $ \s -> s { actionResp = mkResp $ actionResp s }
  where len = (S.pack "Content-Length", S.pack . show . L.length $ text)
        ctypeHeader = (S.pack "Content-Type", S.pack ctype)
        mkResp resp = resp { respHeaders = ctypeHeader : (len : respHeaders resp)
                           , respBody = inumPure text }