{-# OPTIONS_GHC -Wno-missing-export-lists #-}

module Burrito.Internal.Render where

import qualified Burrito.Internal.Type.Case as Case
import qualified Burrito.Internal.Type.Character as Character
import qualified Burrito.Internal.Type.Digit as Digit
import qualified Burrito.Internal.Type.Expression as Expression
import qualified Burrito.Internal.Type.Field as Field
import qualified Burrito.Internal.Type.Literal as Literal
import qualified Burrito.Internal.Type.MaxLength as MaxLength
import qualified Burrito.Internal.Type.Modifier as Modifier
import qualified Burrito.Internal.Type.Name as Name
import qualified Burrito.Internal.Type.Operator as Operator
import qualified Burrito.Internal.Type.Token as Token
import qualified Burrito.Internal.Type.Variable as Variable
import qualified Data.List as List
import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.Text.Lazy as LazyText
import qualified Data.Text.Lazy.Builder as Builder

builderToString :: Builder.Builder -> String
builderToString :: Builder -> String
builderToString = Text -> String
LazyText.unpack (Text -> String) -> (Builder -> Text) -> Builder -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText

token :: Token.Token -> Builder.Builder
token :: Token -> Builder
token Token
x = case Token
x of
  Token.Expression Expression
y -> Expression -> Builder
expression Expression
y
  Token.Literal Literal
y -> Literal -> Builder
literal Literal
y

expression :: Expression.Expression -> Builder.Builder
expression :: Expression -> Builder
expression Expression
x =
  Char -> Builder
Builder.singleton Char
'{'
    Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Operator -> Builder
operator (Expression -> Operator
Expression.operator Expression
x)
    Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Variable -> Builder) -> Builder -> NonEmpty Variable -> Builder
forall a. (a -> Builder) -> Builder -> NonEmpty a -> Builder
sepBy1 Variable -> Builder
variable (Char -> Builder
Builder.singleton Char
',') (Expression -> NonEmpty Variable
Expression.variables Expression
x)
    Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Builder
Builder.singleton Char
'}'

operator :: Operator.Operator -> Builder.Builder
operator :: Operator -> Builder
operator Operator
x = case Operator
x of
  Operator
Operator.Ampersand -> Char -> Builder
Builder.singleton Char
'&'
  Operator
Operator.FullStop -> Char -> Builder
Builder.singleton Char
'.'
  Operator
Operator.None -> Builder
forall a. Monoid a => a
mempty
  Operator
Operator.NumberSign -> Char -> Builder
Builder.singleton Char
'#'
  Operator
Operator.PlusSign -> Char -> Builder
Builder.singleton Char
'+'
  Operator
Operator.QuestionMark -> Char -> Builder
Builder.singleton Char
'?'
  Operator
Operator.Semicolon -> Char -> Builder
Builder.singleton Char
';'
  Operator
Operator.Solidus -> Char -> Builder
Builder.singleton Char
'/'

sepBy1
  :: (a -> Builder.Builder)
  -> Builder.Builder
  -> NonEmpty.NonEmpty a
  -> Builder.Builder
sepBy1 :: (a -> Builder) -> Builder -> NonEmpty a -> Builder
sepBy1 a -> Builder
f Builder
x = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder)
-> (NonEmpty a -> [Builder]) -> NonEmpty a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> [Builder] -> [Builder]
forall a. a -> [a] -> [a]
List.intersperse Builder
x ([Builder] -> [Builder])
-> (NonEmpty a -> [Builder]) -> NonEmpty a -> [Builder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Builder) -> [a] -> [Builder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Builder
f ([a] -> [Builder])
-> (NonEmpty a -> [a]) -> NonEmpty a -> [Builder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty a -> [a]
forall a. NonEmpty a -> [a]
NonEmpty.toList

variable :: Variable.Variable -> Builder.Builder
variable :: Variable -> Builder
variable Variable
x = Name -> Builder
name (Variable -> Name
Variable.name Variable
x) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Modifier -> Builder
modifier (Variable -> Modifier
Variable.modifier Variable
x)

name :: Name.Name -> Builder.Builder
name :: Name -> Builder
name = (Field -> Builder) -> Builder -> NonEmpty Field -> Builder
forall a. (a -> Builder) -> Builder -> NonEmpty a -> Builder
sepBy1 Field -> Builder
field (Char -> Builder
Builder.singleton Char
'.') (NonEmpty Field -> Builder)
-> (Name -> NonEmpty Field) -> Name -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> NonEmpty Field
Name.fields

field :: Field.Field -> Builder.Builder
field :: Field -> Builder
field = (Character Field -> Builder)
-> NonEmpty (Character Field) -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Character Field -> Builder
forall tag. Character tag -> Builder
character (NonEmpty (Character Field) -> Builder)
-> (Field -> NonEmpty (Character Field)) -> Field -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field -> NonEmpty (Character Field)
Field.characters

character :: Character.Character tag -> Builder.Builder
character :: Character tag -> Builder
character Character tag
x = case Character tag
x of
  Character.Encoded Digit
y Digit
z -> Digit -> Digit -> Builder
encodedCharacter Digit
y Digit
z
  Character.Unencoded Char
y -> Char -> Builder
Builder.singleton Char
y

encodedCharacter :: Digit.Digit -> Digit.Digit -> Builder.Builder
encodedCharacter :: Digit -> Digit -> Builder
encodedCharacter Digit
x Digit
y = Char -> Builder
Builder.singleton Char
'%' Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Digit -> Builder
digit Digit
x Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Digit -> Builder
digit Digit
y

digit :: Digit.Digit -> Builder.Builder
digit :: Digit -> Builder
digit Digit
x = Char -> Builder
Builder.singleton (Char -> Builder) -> Char -> Builder
forall a b. (a -> b) -> a -> b
$ case Digit
x of
  Digit
Digit.Ox0 -> Char
'0'
  Digit
Digit.Ox1 -> Char
'1'
  Digit
Digit.Ox2 -> Char
'2'
  Digit
Digit.Ox3 -> Char
'3'
  Digit
Digit.Ox4 -> Char
'4'
  Digit
Digit.Ox5 -> Char
'5'
  Digit
Digit.Ox6 -> Char
'6'
  Digit
Digit.Ox7 -> Char
'7'
  Digit
Digit.Ox8 -> Char
'8'
  Digit
Digit.Ox9 -> Char
'9'
  Digit.OxA Case
Case.Upper -> Char
'A'
  Digit.OxB Case
Case.Upper -> Char
'B'
  Digit.OxC Case
Case.Upper -> Char
'C'
  Digit.OxD Case
Case.Upper -> Char
'D'
  Digit.OxE Case
Case.Upper -> Char
'E'
  Digit.OxF Case
Case.Upper -> Char
'F'
  Digit.OxA Case
Case.Lower -> Char
'a'
  Digit.OxB Case
Case.Lower -> Char
'b'
  Digit.OxC Case
Case.Lower -> Char
'c'
  Digit.OxD Case
Case.Lower -> Char
'd'
  Digit.OxE Case
Case.Lower -> Char
'e'
  Digit.OxF Case
Case.Lower -> Char
'f'

modifier :: Modifier.Modifier -> Builder.Builder
modifier :: Modifier -> Builder
modifier Modifier
x = case Modifier
x of
  Modifier
Modifier.Asterisk -> Char -> Builder
Builder.singleton Char
'*'
  Modifier.Colon MaxLength
y -> Char -> Builder
Builder.singleton Char
':' Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> MaxLength -> Builder
maxLength MaxLength
y
  Modifier
Modifier.None -> Builder
forall a. Monoid a => a
mempty

maxLength :: MaxLength.MaxLength -> Builder.Builder
maxLength :: MaxLength -> Builder
maxLength = String -> Builder
Builder.fromString (String -> Builder)
-> (MaxLength -> String) -> MaxLength -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show (Int -> String) -> (MaxLength -> Int) -> MaxLength -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MaxLength -> Int
MaxLength.count

literal :: Literal.Literal -> Builder.Builder
literal :: Literal -> Builder
literal = (Character Literal -> Builder)
-> NonEmpty (Character Literal) -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Character Literal -> Builder
forall tag. Character tag -> Builder
character (NonEmpty (Character Literal) -> Builder)
-> (Literal -> NonEmpty (Character Literal)) -> Literal -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Literal -> NonEmpty (Character Literal)
Literal.characters