module Happstack.Server.Monads
    ( 
      ServerPartT
    , ServerPart
      
    , Happstack
      
    , ServerMonad(..)
    , mapServerPartT
    , mapServerPartT'
    , UnWebT
    , filterFun
      
    , FilterMonad(..)
    , ignoreFilters
    , addHeaderM
    , getHeaderM
    , setHeaderM
    , neverExpires
      
    , WebMonad(..)
    , escape
    , escape'
      
    , require
    , requireM
    
    , escapeHTTP
    ) where
import Control.Applicative               (Alternative, Applicative)
import Control.Monad                     (MonadPlus(mzero))
import Control.Monad.Error               (Error, ErrorT)
import Control.Monad.Trans               (MonadIO(..),MonadTrans(lift))
import Control.Monad.Trans.Except        (ExceptT)
import Control.Monad.Reader              (ReaderT)
import qualified Control.Monad.Writer.Lazy   as Lazy   (WriterT)
import qualified Control.Monad.Writer.Strict as Strict (WriterT)
import qualified Control.Monad.State.Lazy    as Lazy   (StateT)
import qualified Control.Monad.State.Strict  as Strict (StateT)
import qualified Control.Monad.RWS.Lazy      as Lazy   (RWST)
import qualified Control.Monad.RWS.Strict    as Strict (RWST)
import qualified Data.ByteString.Char8       as B
import Data.Monoid                       (Monoid)
import Happstack.Server.Internal.Monads
import Happstack.Server.Types            (Response, addHeader, getHeader, setHeader)
import Happstack.Server.RqData           (HasRqData)
class ( ServerMonad m, WebMonad Response m, FilterMonad Response m
      , MonadIO m, MonadPlus m, HasRqData m, Monad m, Functor m
      , Applicative m, Alternative m) => Happstack m
instance (Functor m, Monad m, MonadPlus m
         , MonadIO m)            => Happstack (ServerPartT m)
instance (Happstack m)           => Happstack (Lazy.StateT        s m)
instance (Happstack m)           => Happstack (Strict.StateT      s m)
instance (Happstack m)           => Happstack (ReaderT        r     m)
instance (Happstack m, Monoid w) => Happstack (Lazy.WriterT   w     m)
instance (Happstack m, Monoid w) => Happstack (Strict.WriterT   w   m)
instance (Happstack m, Monoid w) => Happstack (Lazy.RWST      r w s m)
instance (Happstack m, Monoid w) => Happstack (Strict.RWST    r w s m)
instance (Happstack m, Error e)  => Happstack (ErrorT e m)
instance (Happstack m, Monoid e) => Happstack (ExceptT e m)
getHeaderM :: (ServerMonad m) => String -> m (Maybe B.ByteString)
getHeaderM a = askRq >>= return . (getHeader a)
addHeaderM :: (FilterMonad Response m) => String -> String -> m ()
addHeaderM a v = composeFilter $ \res-> addHeader a v res
setHeaderM :: (FilterMonad Response m) => String -> String -> m ()
setHeaderM a v = composeFilter $ \res -> setHeader a v res
neverExpires :: (FilterMonad Response m) => m ()
neverExpires = setHeaderM "Expires" "Mon, 31 Dec 2035 12:00:00 GMT"
require :: (MonadIO m, MonadPlus m) => IO (Maybe a) -> (a -> m r) -> m r
require fn handle = do
    mbVal <- liftIO fn
    case mbVal of
        Nothing -> mzero
        Just a -> handle a
requireM :: (MonadTrans t, Monad m, MonadPlus (t m)) => m (Maybe a) -> (a -> t m r) -> t m r
requireM fn handle = do
    mbVal <- lift fn
    case mbVal of
        Nothing -> mzero
        Just a -> handle a