    {-# LANGUAGE CPP               #-}

    module Heist.Splices
      ( ifISplice
      , ifCSplice
      , ifElseISplice
      , ifElseCSplice
      , module Heist.Splices.Apply
      , module Heist.Splices.Bind
      , module Heist.Splices.Cache
      , module Heist.Splices.Html
      , module Heist.Splices.Ignore
      , module Heist.Splices.Markdown
      ) where

    #if !MIN_VERSION_base(4,8,0)
    import           Data.Monoid (Monoid(..))
    #endif

    import qualified Heist.Compiled as C
    import qualified Heist.Interpreted as I
    import           Heist.Splices.Apply
    import           Heist.Splices.Bind
    import           Heist.Splices.Cache
    import           Heist.Splices.Html
    import           Heist.Splices.Ignore
    import           Heist.Splices.Markdown
    import           Heist.Internal.Types.HeistState
    import qualified Text.XmlHtml as X

    ------------------------------------------------------------------------------
    -- | Run the splice contents if given condition is True, make splice disappear
    -- if not.
    ifISplice :: Monad m => Bool -> I.Splice m
    ifISplice cond =
        case cond of
          False -> return []
          True -> I.runChildren

    ------------------------------------------------------------------------------
    -- | Function for constructing if splices that use a runtime predicate
    -- function to determine whether the node's children should be rendered.
    ifCSplice :: Monad m
              => (t -> Bool)
              -> RuntimeSplice m t
              -> C.Splice m
    ifCSplice predicate runtime = do
        chunks <- C.runChildren
        return $ C.yieldRuntime $ do
            a <- runtime
            if predicate a
              then
                C.codeGen chunks
              else
                return mempty

    ------------------------------------------------------------------------------
    -- | Implements an if\/then\/else conditional splice.  It splits its children
    -- around the \<else\/\> element to get the markup to be used for the two cases.
    ifElseISplice :: Monad m => Bool -> I.Splice m
    ifElseISplice cond = getParamNode >>= (rewrite . X.childNodes)
      where
        rewrite nodes =
          let (ns, ns') = break (\n -> X.tagName n==Just "else") nodes
          in I.runNodeList $ if cond then ns else (drop 1 ns')

    ------------------------------------------------------------------------------
    -- | Implements an if\/then\/else conditional splice.  It splits its children
    -- around the \<else\/\> element to get the markup to be used for the two cases.
    ifElseCSplice :: Monad m => Bool -> C.Splice m
    ifElseCSplice cond = getParamNode >>= (rewrite . X.childNodes)
      where rewrite nodes =
              let (ns, ns') = break (\n -> X.tagName n==Just "else") nodes
              in C.runNodeList $ if cond then ns else (drop 1 ns')