{-# 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 :: forall (m :: * -> *). Monad m => Bool -> Splice m
ifISplice Bool
cond =
    case Bool
cond of
      Bool
False -> forall (m :: * -> *) a. Monad m => a -> m a
return []
      Bool
True -> forall (n :: * -> *). Monad n => Splice n
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 :: forall (m :: * -> *) t.
Monad m =>
(t -> Bool) -> RuntimeSplice m t -> Splice m
ifCSplice t -> Bool
predicate RuntimeSplice m t
runtime = do
    DList (Chunk m)
chunks <- forall (n :: * -> *). Monad n => Splice n
C.runChildren
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (n :: * -> *). RuntimeSplice n Builder -> DList (Chunk n)
C.yieldRuntime forall a b. (a -> b) -> a -> b
$ do
        t
a <- RuntimeSplice m t
runtime
        if t -> Bool
predicate t
a
          then
            forall (n :: * -> *).
Monad n =>
DList (Chunk n) -> RuntimeSplice n Builder
C.codeGen DList (Chunk m)
chunks
          else
            forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Monoid a => a
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 :: forall (m :: * -> *). Monad m => Bool -> Splice m
ifElseISplice Bool
cond = forall (m :: * -> *) (n :: * -> *). Monad m => HeistT n m Node
getParamNode forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (forall {n :: * -> *}. Monad n => Template -> Splice n
rewrite forall b c a. (b -> c) -> (a -> b) -> a -> c
. Node -> Template
X.childNodes)
  where
    rewrite :: Template -> Splice n
rewrite Template
nodes = 
      let (Template
ns, Template
ns') = forall a. (a -> Bool) -> [a] -> ([a], [a])
break (\Node
n -> Node -> Maybe Text
X.tagName Node
nforall a. Eq a => a -> a -> Bool
==forall a. a -> Maybe a
Just Text
"else") Template
nodes
      in forall {n :: * -> *}. Monad n => Template -> Splice n
I.runNodeList forall a b. (a -> b) -> a -> b
$ if Bool
cond then Template
ns else (forall a. Int -> [a] -> [a]
drop Int
1 Template
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 :: forall (m :: * -> *). Monad m => Bool -> Splice m
ifElseCSplice Bool
cond = forall (m :: * -> *) (n :: * -> *). Monad m => HeistT n m Node
getParamNode forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (forall {n :: * -> *}. Monad n => Template -> Splice n
rewrite forall b c a. (b -> c) -> (a -> b) -> a -> c
. Node -> Template
X.childNodes)
  where rewrite :: Template -> Splice n
rewrite Template
nodes = 
          let (Template
ns, Template
ns') = forall a. (a -> Bool) -> [a] -> ([a], [a])
break (\Node
n -> Node -> Maybe Text
X.tagName Node
nforall a. Eq a => a -> a -> Bool
==forall a. a -> Maybe a
Just Text
"else") Template
nodes
          in forall {n :: * -> *}. Monad n => Template -> Splice n
C.runNodeList forall a b. (a -> b) -> a -> b
$ if Bool
cond then Template
ns else (forall a. Int -> [a] -> [a]
drop Int
1 Template
ns')