{-# LANGUAGE CPP               #-}
{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}

module Text.Glabrous.Types where

import           Control.Arrow       (second)
import           Data.Aeson
#if MIN_VERSION_aeson(2,0,0)
import qualified Data.Aeson.KeyMap   as KM
#endif
import qualified Data.HashMap.Strict as H
import           Data.Serialize
import           Data.Serialize.Text ()
import qualified Data.Text           as T
import           GHC.Generics

data Token
  = Tag !T.Text
  | Literal !T.Text
  deriving (Token -> Token -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Token -> Token -> Bool
$c/= :: Token -> Token -> Bool
== :: Token -> Token -> Bool
$c== :: Token -> Token -> Bool
Eq, Int -> Token -> ShowS
[Token] -> ShowS
Token -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Token] -> ShowS
$cshowList :: [Token] -> ShowS
show :: Token -> String
$cshow :: Token -> String
showsPrec :: Int -> Token -> ShowS
$cshowsPrec :: Int -> Token -> ShowS
Show, forall x. Rep Token x -> Token
forall x. Token -> Rep Token x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Token x -> Token
$cfrom :: forall x. Token -> Rep Token x
Generic)

instance Serialize Token

newtype Template =
  Template
    { Template -> [Token]
content :: [Token] }
    deriving (Template -> Template -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Template -> Template -> Bool
$c/= :: Template -> Template -> Bool
== :: Template -> Template -> Bool
$c== :: Template -> Template -> Bool
Eq, Int -> Template -> ShowS
[Template] -> ShowS
Template -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Template] -> ShowS
$cshowList :: [Template] -> ShowS
show :: Template -> String
$cshow :: Template -> String
showsPrec :: Int -> Template -> ShowS
$cshowsPrec :: Int -> Template -> ShowS
Show, forall x. Rep Template x -> Template
forall x. Template -> Rep Template x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Template x -> Template
$cfrom :: forall x. Template -> Rep Template x
Generic)

instance Serialize Template

newtype Context =
  Context
    { Context -> HashMap Text Text
variables :: H.HashMap T.Text T.Text }
    deriving (Context -> Context -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Context -> Context -> Bool
$c/= :: Context -> Context -> Bool
== :: Context -> Context -> Bool
$c== :: Context -> Context -> Bool
Eq, Int -> Context -> ShowS
[Context] -> ShowS
Context -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Context] -> ShowS
$cshowList :: [Context] -> ShowS
show :: Context -> String
$cshow :: Context -> String
showsPrec :: Int -> Context -> ShowS
$cshowsPrec :: Int -> Context -> ShowS
Show)

instance ToJSON Context where
  toJSON :: Context -> Value
toJSON (Context HashMap Text Text
h) =
#if MIN_VERSION_aeson(2,0,0)
    [Pair] -> Value
object (forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second Text -> Value
String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall v. KeyMap v -> [(Key, v)]
KM.toList (forall v. HashMap Text v -> KeyMap v
KM.fromHashMapText HashMap Text Text
h))
#else
    object (second String <$> H.toList h)
#endif

instance FromJSON Context where
  parseJSON :: Value -> Parser Context
parseJSON (Object Object
o) = do
#if MIN_VERSION_aeson(2,0,0)
    let t :: HashMap Text Value
t = forall v. KeyMap v -> HashMap Text v
KM.toHashMapText Object
o
#else
    let t = o
#endif
    forall (f :: * -> *) a. Applicative f => a -> f a
pure Context { variables :: HashMap Text Text
variables = forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
H.fromList (forall {a}. (a, Value) -> (a, Text)
fromJSONString forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall k v. HashMap k v -> [(k, v)]
H.toList HashMap Text Value
t) }
    where
      fromJSONString :: (a, Value) -> (a, Text)
fromJSONString (a
k,String Text
v) = (a
k,Text
v)
      fromJSONString (a, Value)
_            = forall a. HasCallStack => String -> a
error String
"Expected a JSON String in second element of pair"
  parseJSON Value
_          = forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Expected a JSON object"

data Result
  = Final !T.Text
  | Partial { Result -> Template
template :: !Template, Result -> Context
context :: !Context }
  deriving (Result -> Result -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Result -> Result -> Bool
$c/= :: Result -> Result -> Bool
== :: Result -> Result -> Bool
$c== :: Result -> Result -> Bool
Eq, Int -> Result -> ShowS
[Result] -> ShowS
Result -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Result] -> ShowS
$cshowList :: [Result] -> ShowS
show :: Result -> String
$cshow :: Result -> String
showsPrec :: Int -> Result -> ShowS
$cshowsPrec :: Int -> Result -> ShowS
Show)