{-# LANGUAGE BangPatterns               #-}
{-# LANGUAGE CPP                        #-}
{-# LANGUAGE DeriveDataTypeable         #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE UndecidableInstances       #-}

{-|

Internal types and accessors.  There are no guarantees that heist will
preserve backwards compatibility for symbols in this module.  If you use them,
no complaining when your code breaks.

-}

module Heist.Internal.Types
  ( module Heist.Internal.Types.HeistState
  , module Heist.Internal.Types
  ) where

------------------------------------------------------------------------------
import           Data.HashMap.Strict (HashMap)
import           Data.Text (Text)

#if !MIN_VERSION_base(4,8,0)
import           Control.Applicative
#endif
#if !MIN_VERSION_base(4,11,0)
import           Data.Semigroup
#endif

------------------------------------------------------------------------------
import qualified Heist.Compiled.Internal       as C
import qualified Heist.Interpreted.Internal    as I
import           Heist.Internal.Types.HeistState
------------------------------------------------------------------------------


------------------------------------------------------------------------------
type TemplateRepo = HashMap TPath DocumentFile


------------------------------------------------------------------------------
-- | An IO action for getting a template repo from this location.  By not just
-- using a directory path here, we support templates loaded from a database,
-- retrieved from the network, or anything else you can think of.
type TemplateLocation = IO (Either [String] TemplateRepo)


------------------------------------------------------------------------------
-- | My lens creation function to avoid a dependency on lens.
lens :: Functor f => (t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b
lens :: forall (f :: * -> *) t1 t a b.
Functor f =>
(t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b
lens t1 -> t
sa t1 -> a -> b
sbt t -> f a
afb t1
s = t1 -> a -> b
sbt t1
s forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t -> f a
afb (t1 -> t
sa t1
s)


------------------------------------------------------------------------------
-- | The splices and templates Heist will use.  To bind a splice simply
-- include it in the appropriate place here.
data SpliceConfig m = SpliceConfig
    { forall (m :: * -> *). SpliceConfig m -> Splices (Splice m)
_scInterpretedSplices     :: Splices (I.Splice m)
        -- ^ Interpreted splices are the splices that Heist has always had.
        -- They return a list of nodes and are processed at runtime.
    , forall (m :: * -> *). SpliceConfig m -> Splices (Splice IO)
_scLoadTimeSplices        :: Splices (I.Splice IO)
        -- ^ Load time splices are like interpreted splices because they
        -- return a list of nodes.  But they are like compiled splices because
        -- they are processed once at load time.  All of Heist's built-in
        -- splices should be used as load time splices.
    , forall (m :: * -> *). SpliceConfig m -> Splices (Splice m)
_scCompiledSplices        :: Splices (C.Splice m)
        -- ^ Compiled splices return a DList of Chunks and are processed at
        -- load time to generate a runtime monad action that will be used to
        -- render the template.
    , forall (m :: * -> *). SpliceConfig m -> Splices (AttrSplice m)
_scAttributeSplices       :: Splices (AttrSplice m)
        -- ^ Attribute splices are bound to attribute names and return a list
        -- of attributes.
    , forall (m :: * -> *). SpliceConfig m -> [TemplateLocation]
_scTemplateLocations      :: [TemplateLocation]
        -- ^ A list of all the locations that Heist should get its templates
        -- from.
    , forall (m :: * -> *). SpliceConfig m -> TPath -> Bool
_scCompiledTemplateFilter :: TPath -> Bool
        -- ^ Predicate function to control which templates to compile.  Using
        -- templates filtered out with this is still possible via
        -- callTemplate.
    }


------------------------------------------------------------------------------
-- | Lens for interpreted splices
-- :: Simple Lens (SpliceConfig m) (Splices (I.Splice m))
scInterpretedSplices
    :: Functor f
    => (Splices (I.Splice m) -> f (Splices (I.Splice m)))
    -> SpliceConfig m -> f (SpliceConfig m)
scInterpretedSplices :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (Splice m) -> f (Splices (Splice m)))
-> SpliceConfig m -> f (SpliceConfig m)
scInterpretedSplices = forall (f :: * -> *) t1 t a b.
Functor f =>
(t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b
lens forall (m :: * -> *). SpliceConfig m -> Splices (Splice m)
_scInterpretedSplices forall {m :: * -> *}.
SpliceConfig m -> Splices (Splice m) -> SpliceConfig m
setter
  where
    setter :: SpliceConfig m -> Splices (Splice m) -> SpliceConfig m
setter SpliceConfig m
sc Splices (Splice m)
v = SpliceConfig m
sc { _scInterpretedSplices :: Splices (Splice m)
_scInterpretedSplices = Splices (Splice m)
v }


------------------------------------------------------------------------------
-- | Lens for load time splices
-- :: Simple Lens (SpliceConfig m) (Splices (I.Splice IO))
scLoadTimeSplices
    :: Functor f
    => (Splices (I.Splice IO) -> f (Splices (I.Splice IO)))
    -> SpliceConfig m -> f (SpliceConfig m)
scLoadTimeSplices :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (Splice IO) -> f (Splices (Splice IO)))
-> SpliceConfig m -> f (SpliceConfig m)
scLoadTimeSplices = forall (f :: * -> *) t1 t a b.
Functor f =>
(t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b
lens forall (m :: * -> *). SpliceConfig m -> Splices (Splice IO)
_scLoadTimeSplices forall {m :: * -> *}.
SpliceConfig m -> Splices (Splice IO) -> SpliceConfig m
setter
  where
    setter :: SpliceConfig m -> Splices (Splice IO) -> SpliceConfig m
setter SpliceConfig m
sc Splices (Splice IO)
v = SpliceConfig m
sc { _scLoadTimeSplices :: Splices (Splice IO)
_scLoadTimeSplices = Splices (Splice IO)
v }


------------------------------------------------------------------------------
-- | Lens for complied splices
-- :: Simple Lens (SpliceConfig m) (Splices (C.Splice m))
scCompiledSplices
    :: Functor f
    => (Splices (C.Splice m) -> f (Splices (C.Splice m)))
    -> SpliceConfig m -> f (SpliceConfig m)
scCompiledSplices :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (Splice m) -> f (Splices (Splice m)))
-> SpliceConfig m -> f (SpliceConfig m)
scCompiledSplices = forall (f :: * -> *) t1 t a b.
Functor f =>
(t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b
lens forall (m :: * -> *). SpliceConfig m -> Splices (Splice m)
_scCompiledSplices forall {m :: * -> *}.
SpliceConfig m -> Splices (Splice m) -> SpliceConfig m
setter
  where
    setter :: SpliceConfig m -> Splices (Splice m) -> SpliceConfig m
setter SpliceConfig m
sc Splices (Splice m)
v = SpliceConfig m
sc { _scCompiledSplices :: Splices (Splice m)
_scCompiledSplices = Splices (Splice m)
v }


------------------------------------------------------------------------------
-- | Lens for attribute splices
-- :: Simple Lens (SpliceConfig m) (Splices (AttrSplice m))
scAttributeSplices
    :: Functor f
    => (Splices (AttrSplice m) -> f (Splices (AttrSplice m)))
    -> SpliceConfig m -> f (SpliceConfig m)
scAttributeSplices :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (AttrSplice m) -> f (Splices (AttrSplice m)))
-> SpliceConfig m -> f (SpliceConfig m)
scAttributeSplices = forall (f :: * -> *) t1 t a b.
Functor f =>
(t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b
lens forall (m :: * -> *). SpliceConfig m -> Splices (AttrSplice m)
_scAttributeSplices forall {m :: * -> *}.
SpliceConfig m -> Splices (AttrSplice m) -> SpliceConfig m
setter
  where
    setter :: SpliceConfig m -> Splices (AttrSplice m) -> SpliceConfig m
setter SpliceConfig m
sc Splices (AttrSplice m)
v = SpliceConfig m
sc { _scAttributeSplices :: Splices (AttrSplice m)
_scAttributeSplices = Splices (AttrSplice m)
v }


------------------------------------------------------------------------------
-- | Lens for template locations
-- :: Simple Lens (SpliceConfig m) [TemplateLocation]
scTemplateLocations
    :: Functor f
    => ([TemplateLocation] -> f [TemplateLocation])
    -> SpliceConfig m -> f (SpliceConfig m)
scTemplateLocations :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
([TemplateLocation] -> f [TemplateLocation])
-> SpliceConfig m -> f (SpliceConfig m)
scTemplateLocations = forall (f :: * -> *) t1 t a b.
Functor f =>
(t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b
lens forall (m :: * -> *). SpliceConfig m -> [TemplateLocation]
_scTemplateLocations forall {m :: * -> *}.
SpliceConfig m -> [TemplateLocation] -> SpliceConfig m
setter
  where
    setter :: SpliceConfig m -> [TemplateLocation] -> SpliceConfig m
setter SpliceConfig m
sc [TemplateLocation]
v = SpliceConfig m
sc { _scTemplateLocations :: [TemplateLocation]
_scTemplateLocations = [TemplateLocation]
v }


------------------------------------------------------------------------------
-- | Lens for compiled template filter
-- :: Simple Lens (SpliceConfig m) (TBool -> Bool)
scCompiledTemplateFilter
    :: Functor f
    => ((TPath -> Bool) -> f (TPath -> Bool))
    -> SpliceConfig m -> f (SpliceConfig m)
scCompiledTemplateFilter :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
((TPath -> Bool) -> f (TPath -> Bool))
-> SpliceConfig m -> f (SpliceConfig m)
scCompiledTemplateFilter = forall (f :: * -> *) t1 t a b.
Functor f =>
(t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b
lens forall (m :: * -> *). SpliceConfig m -> TPath -> Bool
_scCompiledTemplateFilter forall {m :: * -> *}.
SpliceConfig m -> (TPath -> Bool) -> SpliceConfig m
setter
  where
    setter :: SpliceConfig m -> (TPath -> Bool) -> SpliceConfig m
setter SpliceConfig m
sc TPath -> Bool
v = SpliceConfig m
sc { _scCompiledTemplateFilter :: TPath -> Bool
_scCompiledTemplateFilter = TPath -> Bool
v }


instance Semigroup (SpliceConfig m) where
    SpliceConfig Splices (Splice m)
a1 Splices (Splice IO)
b1 Splices (Splice m)
c1 Splices (AttrSplice m)
d1 [TemplateLocation]
e1 TPath -> Bool
f1 <> :: SpliceConfig m -> SpliceConfig m -> SpliceConfig m
<> SpliceConfig Splices (Splice m)
a2 Splices (Splice IO)
b2 Splices (Splice m)
c2 Splices (AttrSplice m)
d2 [TemplateLocation]
e2 TPath -> Bool
f2 =
      forall (m :: * -> *).
Splices (Splice m)
-> Splices (Splice IO)
-> Splices (Splice m)
-> Splices (AttrSplice m)
-> [TemplateLocation]
-> (TPath -> Bool)
-> SpliceConfig m
SpliceConfig (Splices (Splice m)
a1 forall a. Semigroup a => a -> a -> a
<> Splices (Splice m)
a2) (Splices (Splice IO)
b1 forall a. Semigroup a => a -> a -> a
<> Splices (Splice IO)
b2) (Splices (Splice m)
c1 forall a. Semigroup a => a -> a -> a
<> Splices (Splice m)
c2)
                   (Splices (AttrSplice m)
d1 forall a. Semigroup a => a -> a -> a
<> Splices (AttrSplice m)
d2) ([TemplateLocation]
e1 forall a. Semigroup a => a -> a -> a
<> [TemplateLocation]
e2) (\TPath
x -> TPath -> Bool
f1 TPath
x Bool -> Bool -> Bool
&& TPath -> Bool
f2 TPath
x)

instance Monoid (SpliceConfig m) where
    mempty :: SpliceConfig m
mempty = forall (m :: * -> *).
Splices (Splice m)
-> Splices (Splice IO)
-> Splices (Splice m)
-> Splices (AttrSplice m)
-> [TemplateLocation]
-> (TPath -> Bool)
-> SpliceConfig m
SpliceConfig forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty (forall a b. a -> b -> a
const Bool
True)
#if !MIN_VERSION_base(4,11,0)
    mappend = (<>)
#endif


data HeistConfig m = HeistConfig
    { forall (m :: * -> *). HeistConfig m -> SpliceConfig m
_hcSpliceConfig  :: SpliceConfig m
        -- ^ Splices and templates
    , forall (m :: * -> *). HeistConfig m -> Text
_hcNamespace     :: Text
        -- ^ A namespace to use for all tags that are bound to splices.  Use
        -- empty string for no namespace.
    , forall (m :: * -> *). HeistConfig m -> Bool
_hcErrorNotBound :: Bool
        -- ^ Whether to throw an error when a tag wih the heist namespace does
        -- not correspond to a bound splice.  When not using a namespace, this
        -- flag is ignored.
    }


------------------------------------------------------------------------------
-- | Lens for the SpliceConfig
-- :: Simple Lens (HeistConfig m) (SpliceConfig m)
hcSpliceConfig
    :: Functor f
    => ((SpliceConfig m) -> f (SpliceConfig m))
    -> HeistConfig m -> f (HeistConfig m)
hcSpliceConfig :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
(SpliceConfig m -> f (SpliceConfig m))
-> HeistConfig m -> f (HeistConfig m)
hcSpliceConfig = forall (f :: * -> *) t1 t a b.
Functor f =>
(t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b
lens forall (m :: * -> *). HeistConfig m -> SpliceConfig m
_hcSpliceConfig forall {m :: * -> *} {m :: * -> *}.
HeistConfig m -> SpliceConfig m -> HeistConfig m
setter
  where
    setter :: HeistConfig m -> SpliceConfig m -> HeistConfig m
setter HeistConfig m
hc SpliceConfig m
v = HeistConfig m
hc { _hcSpliceConfig :: SpliceConfig m
_hcSpliceConfig = SpliceConfig m
v }


------------------------------------------------------------------------------
-- | Lens for the namespace
-- :: Simple Lens (HeistConfig m) Text
hcNamespace
    :: Functor f
    => (Text -> f Text)
    -> HeistConfig m -> f (HeistConfig m)
hcNamespace :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Text -> f Text) -> HeistConfig m -> f (HeistConfig m)
hcNamespace = forall (f :: * -> *) t1 t a b.
Functor f =>
(t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b
lens forall (m :: * -> *). HeistConfig m -> Text
_hcNamespace forall {m :: * -> *}. HeistConfig m -> Text -> HeistConfig m
setter
  where
    setter :: HeistConfig m -> Text -> HeistConfig m
setter HeistConfig m
hc Text
v = HeistConfig m
hc { _hcNamespace :: Text
_hcNamespace = Text
v }


------------------------------------------------------------------------------
-- | Lens for the namespace error flag
-- :: Simple Lens (HeistConfig m) Bool
hcErrorNotBound
    :: Functor f
    => (Bool -> f Bool)
    -> HeistConfig m -> f (HeistConfig m)
hcErrorNotBound :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Bool -> f Bool) -> HeistConfig m -> f (HeistConfig m)
hcErrorNotBound = forall (f :: * -> *) t1 t a b.
Functor f =>
(t1 -> t) -> (t1 -> a -> b) -> (t -> f a) -> t1 -> f b
lens forall (m :: * -> *). HeistConfig m -> Bool
_hcErrorNotBound forall {m :: * -> *}. HeistConfig m -> Bool -> HeistConfig m
setter
  where
    setter :: HeistConfig m -> Bool -> HeistConfig m
setter HeistConfig m
hc Bool
v = HeistConfig m
hc { _hcErrorNotBound :: Bool
_hcErrorNotBound = Bool
v }


------------------------------------------------------------------------------
-- | Lens for interpreted splices
-- :: Simple Lens (HeistConfig m) (Splices (I.Splice m))
hcInterpretedSplices
    :: Functor f
    => (Splices (I.Splice m) -> f (Splices (I.Splice m)))
    -> HeistConfig m -> f (HeistConfig m)
hcInterpretedSplices :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (Splice m) -> f (Splices (Splice m)))
-> HeistConfig m -> f (HeistConfig m)
hcInterpretedSplices = forall (f :: * -> *) (m :: * -> *).
Functor f =>
(SpliceConfig m -> f (SpliceConfig m))
-> HeistConfig m -> f (HeistConfig m)
hcSpliceConfig forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (Splice m) -> f (Splices (Splice m)))
-> SpliceConfig m -> f (SpliceConfig m)
scInterpretedSplices


------------------------------------------------------------------------------
-- | Lens for load time splices
-- :: Simple Lens (HeistConfig m) (Splices (I.Splice IO))
hcLoadTimeSplices
    :: Functor f
    => (Splices (I.Splice IO) -> f (Splices (I.Splice IO)))
    -> HeistConfig m -> f (HeistConfig m)
hcLoadTimeSplices :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (Splice IO) -> f (Splices (Splice IO)))
-> HeistConfig m -> f (HeistConfig m)
hcLoadTimeSplices = forall (f :: * -> *) (m :: * -> *).
Functor f =>
(SpliceConfig m -> f (SpliceConfig m))
-> HeistConfig m -> f (HeistConfig m)
hcSpliceConfig forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (Splice IO) -> f (Splices (Splice IO)))
-> SpliceConfig m -> f (SpliceConfig m)
scLoadTimeSplices 


------------------------------------------------------------------------------
-- | Lens for compiled splices
-- :: Simple Lens (HeistConfig m) (Splices (C.Splice m))
hcCompiledSplices
    :: Functor f
    => (Splices (C.Splice m) -> f (Splices (C.Splice m)))
    -> HeistConfig m -> f (HeistConfig m)
hcCompiledSplices :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (Splice m) -> f (Splices (Splice m)))
-> HeistConfig m -> f (HeistConfig m)
hcCompiledSplices = forall (f :: * -> *) (m :: * -> *).
Functor f =>
(SpliceConfig m -> f (SpliceConfig m))
-> HeistConfig m -> f (HeistConfig m)
hcSpliceConfig forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (Splice m) -> f (Splices (Splice m)))
-> SpliceConfig m -> f (SpliceConfig m)
scCompiledSplices 


------------------------------------------------------------------------------
-- | Lens for attribute splices
-- :: Simple Lens (HeistConfig m) (Splices (AttrSplice m))
hcAttributeSplices
    :: Functor f
    => (Splices (AttrSplice m) -> f (Splices (AttrSplice m)))
    -> HeistConfig m -> f (HeistConfig m)
hcAttributeSplices :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (AttrSplice m) -> f (Splices (AttrSplice m)))
-> HeistConfig m -> f (HeistConfig m)
hcAttributeSplices = forall (f :: * -> *) (m :: * -> *).
Functor f =>
(SpliceConfig m -> f (SpliceConfig m))
-> HeistConfig m -> f (HeistConfig m)
hcSpliceConfig forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) (m :: * -> *).
Functor f =>
(Splices (AttrSplice m) -> f (Splices (AttrSplice m)))
-> SpliceConfig m -> f (SpliceConfig m)
scAttributeSplices 


------------------------------------------------------------------------------
-- | Lens for template locations
-- :: Simple Lens (HeistConfig m) [TemplateLocation]
hcTemplateLocations
    :: Functor f
    => ([TemplateLocation] -> f [TemplateLocation])
    -> HeistConfig m -> f (HeistConfig m)
hcTemplateLocations :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
([TemplateLocation] -> f [TemplateLocation])
-> HeistConfig m -> f (HeistConfig m)
hcTemplateLocations = forall (f :: * -> *) (m :: * -> *).
Functor f =>
(SpliceConfig m -> f (SpliceConfig m))
-> HeistConfig m -> f (HeistConfig m)
hcSpliceConfig forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) (m :: * -> *).
Functor f =>
([TemplateLocation] -> f [TemplateLocation])
-> SpliceConfig m -> f (SpliceConfig m)
scTemplateLocations 


------------------------------------------------------------------------------
-- | Lens for compiled template filter
-- :: Simple Lens (SpliceConfig m) (TBool -> Bool)
hcCompiledTemplateFilter
    :: Functor f
    => ((TPath -> Bool) -> f (TPath -> Bool))
    -> HeistConfig m -> f (HeistConfig m)
hcCompiledTemplateFilter :: forall (f :: * -> *) (m :: * -> *).
Functor f =>
((TPath -> Bool) -> f (TPath -> Bool))
-> HeistConfig m -> f (HeistConfig m)
hcCompiledTemplateFilter = forall (f :: * -> *) (m :: * -> *).
Functor f =>
(SpliceConfig m -> f (SpliceConfig m))
-> HeistConfig m -> f (HeistConfig m)
hcSpliceConfig forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) (m :: * -> *).
Functor f =>
((TPath -> Bool) -> f (TPath -> Bool))
-> SpliceConfig m -> f (SpliceConfig m)
scCompiledTemplateFilter