{-# LANGUAGE PatternSynonyms #-}

module Argo
    ( Value
    , Array
    , Pair
    , Object
    , pattern Null
    , pattern Boolean
    , pattern Number
    , pattern String
    , pattern Array
    , pattern Object
    , pattern Pair
    , encode
    , decode
    , FromValue.FromValue(..)
    , ToValue.ToValue(..)
    ) where

import qualified Argo.Class.FromValue as FromValue
import qualified Argo.Class.ToValue as ToValue
import qualified Argo.Decoder as Decoder
import qualified Argo.Type.Array as Array
import qualified Argo.Type.Boolean as Boolean
import qualified Argo.Type.Null as Null
import qualified Argo.Type.Number as Number
import qualified Argo.Type.Object as Object
import qualified Argo.Type.Pair as Pair
import qualified Argo.Type.String as String
import qualified Argo.Type.Value as Value
import qualified Data.Array
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Builder as Builder
import qualified Data.Text as Text

type Value = Value.Value

type Array = Data.Array.Array Int Value

type Pair = Pair.Pair String.String Value

type Object = Data.Array.Array Int Pair

pattern Null :: Value
pattern $bNull :: Value
$mNull :: forall r. Value -> (Void# -> r) -> (Void# -> r) -> r
Null = Value.Null (Null.Null ())

pattern Boolean :: Bool -> Value
pattern $bBoolean :: Bool -> Value
$mBoolean :: forall r. Value -> (Bool -> r) -> (Void# -> r) -> r
Boolean x = Value.Boolean (Boolean.Boolean x)

pattern Number :: Integer -> Integer -> Value
pattern $bNumber :: Integer -> Integer -> Value
$mNumber :: forall r. Value -> (Integer -> Integer -> r) -> (Void# -> r) -> r
Number x y <- Value.Number (Number.Number x y) where
    Number Integer
x Integer
y = Number -> Value
Value.Number (Number -> Value) -> (Number -> Number) -> Number -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Number -> Number
Number.normalize (Number -> Value) -> Number -> Value
forall a b. (a -> b) -> a -> b
$ Integer -> Integer -> Number
Number.Number Integer
x Integer
y

pattern String :: Text.Text -> Value
pattern $bString :: Text -> Value
$mString :: forall r. Value -> (Text -> r) -> (Void# -> r) -> r
String x = Value.String (String.String x)

pattern Array :: Array -> Value
pattern $bArray :: Array -> Value
$mArray :: forall r. Value -> (Array -> r) -> (Void# -> r) -> r
Array x = Value.Array (Array.Array x)

pattern Object :: Object -> Value
pattern $bObject :: Object -> Value
$mObject :: forall r. Value -> (Object -> r) -> (Void# -> r) -> r
Object x = Value.Object (Object.Object x)

{-# COMPLETE Null, Boolean, Number, String, Array, Object #-}

pattern Pair :: Text.Text -> Value -> Pair
pattern $bPair :: Text -> Value -> Pair
$mPair :: forall r. Pair -> (Text -> Value -> r) -> (Void# -> r) -> r
Pair k v = Pair.Pair (String.String k, v)

{-# COMPLETE Pair #-}

encode :: ToValue.ToValue a => a -> Builder.Builder
encode :: a -> Builder
encode = Value -> Builder
Value.encode (Value -> Builder) -> (a -> Value) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Value
forall a. ToValue a => a -> Value
ToValue.toValue

decode :: FromValue.FromValue a => ByteString.ByteString -> Maybe a
decode :: ByteString -> Maybe a
decode ByteString
x = do
    (ByteString
_, Value
y) <- Decoder Value -> ByteString -> Maybe (ByteString, Value)
forall a. Decoder a -> ByteString -> Maybe (ByteString, a)
Decoder.run (Decoder ()
Decoder.spaces Decoder () -> Decoder Value -> Decoder Value
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Decoder Value
Value.decode Decoder Value -> Decoder () -> Decoder Value
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Decoder ()
Decoder.eof) ByteString
x
    Value -> Maybe a
forall a. FromValue a => Value -> Maybe a
FromValue.fromValue Value
y