module Heist.TemplateDirectory
    ( TemplateDirectory
    , newTemplateDirectory
    , newTemplateDirectory'
    , getDirectoryHS
    , getDirectoryCTS
    , reloadTemplateDirectory
    ) where
import           Control.Concurrent
import           Control.Monad
import           Control.Monad.Trans
import           Heist
import           Heist.Internal.Types
import           Heist.Splices.Cache
data TemplateDirectory n
    = TemplateDirectory
        FilePath
        (HeistConfig n)
        (MVar (HeistState n))
        (MVar CacheTagState)
newTemplateDirectory
    :: MonadIO n
    => FilePath
    -> HeistConfig n
    
    -> IO (Either [String] (TemplateDirectory n))
newTemplateDirectory dir hc = do
    let sc = (_hcSpliceConfig hc) { _scTemplateLocations = [loadTemplates dir] }
    let hc' = hc { _hcSpliceConfig = sc }
    epair <- initHeistWithCacheTag hc'
    case epair of
      Left es -> return $ Left es
      Right (hs,cts) -> do
        tsMVar <- liftIO $ newMVar hs
        ctsMVar <- liftIO $ newMVar cts
        return $ Right $ TemplateDirectory dir hc' tsMVar ctsMVar
newTemplateDirectory'
    :: MonadIO n
    => FilePath
    -> HeistConfig n
    -> IO (TemplateDirectory n)
newTemplateDirectory' dir hc = do
    res <- newTemplateDirectory dir hc
    either (error . concat) return res
getDirectoryHS :: (MonadIO n)
               => TemplateDirectory n
               -> IO (HeistState n)
getDirectoryHS (TemplateDirectory _ _ tsMVar _) =
    liftIO $ readMVar $ tsMVar
getDirectoryCTS :: TemplateDirectory n -> IO CacheTagState
getDirectoryCTS (TemplateDirectory _ _ _ ctsMVar) = readMVar ctsMVar
reloadTemplateDirectory :: (MonadIO n)
                        => TemplateDirectory n
                        -> IO (Either String ())
reloadTemplateDirectory (TemplateDirectory p hc tsMVar ctsMVar) = do
    let sc = (_hcSpliceConfig hc) { _scTemplateLocations = [loadTemplates p] }
    ehs <- initHeistWithCacheTag (hc { _hcSpliceConfig = sc })
    leftPass ehs $ \(hs,cts) -> do
        modifyMVar_ tsMVar (const $ return hs)
        modifyMVar_ ctsMVar (const $ return cts)
leftPass :: Monad m => Either [String] b -> (b -> m c) -> m (Either String c)
leftPass e m = either (return . Left . loadError . concat)
                      (liftM Right . m) e
  where
    loadError = (++) ("Error loading templates: " :: String)