module Web.Spock
    ( 
      spock, SpockM, SpockAction
     
    , get, post, C.head, put, delete, patch, defRoute, Http.StdMethod (..)
     
    , request, header, cookie, body, jsonBody, files, UploadedFile (..)
    , params, param
     
    , setStatus, setHeader, redirect, setCookie, setCookie', bytes, lazyBytes
    , text, html, file, json, blaze
     
    , middleware
      
    , PoolOrConn (..), ConnBuilder (..), PoolCfg (..)
      
    , HasSpock (runQuery, getState)
      
    , SessionCfg (..)
    , readSession, writeSession, modifySession
      
    , SafeAction (..)
    , safeActionPath
      
    , runForm
      
    , SpockT, ActionT, spockT
      
    , getSpockHeart, runSpockIO, WebStateM, WebState
    )
where
import Web.Spock.Core
import Web.Spock.Digestive
import Web.Spock.Monad
import Web.Spock.SafeActions
import Web.Spock.SessionManager
import Web.Spock.Types
import qualified Web.Spock.Core as C
import Control.Applicative
import Control.Monad.Trans.Reader
import Control.Monad.Trans.Resource
import Data.Pool
import qualified Network.HTTP.Types as Http
spock :: Int -> SessionCfg sess -> PoolOrConn conn -> st -> SpockM conn sess st () -> IO ()
spock port sessionCfg poolOrConn initialState defs =
    do sessionMgr <- createSessionManager sessionCfg
       connectionPool <-
           case poolOrConn of
             PCConduitPool p ->
                 return (ConduitPool p)
             PCPool p ->
                 return (DataPool p)
             PCConn cb ->
                 let pc = cb_poolConfiguration cb
                 in DataPool <$> createPool (cb_createConn cb) (cb_destroyConn cb)
                                  (pc_stripes pc) (pc_keepOpenTime pc)
                                   (pc_resPerStripe pc)
       let internalState =
               WebState
               { web_dbConn = connectionPool
               , web_sessionMgr = sessionMgr
               , web_state = initialState
               }
           runM m = runResourceT $ runReaderT (runWebStateM m) internalState
       spockT port runM $
               do middleware (sm_middleware sessionMgr)
                  hookSafeActions
                  defs
writeSession :: sess -> SpockAction conn sess st ()
writeSession d =
    do mgr <- getSessMgr
       (sm_writeSession mgr) d
modifySession :: (sess -> sess) -> SpockAction conn sess st ()
modifySession f =
    do mgr <- getSessMgr
       (sm_modifySession mgr) f
readSession :: SpockAction conn sess st sess
readSession =
    do mgr <- getSessMgr
       sm_readSession mgr