module Miso.GraphQL.Class where

import Data.List.NonEmpty (NonEmpty)
import Data.List.NonEmpty qualified as NonEmpty
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Maybe (isJust)
import GHC.Float (float2Double)
import Miso.GraphQL.AST
import Miso.JSON (ToJSON (..))
import Miso.JSON qualified as JSON
import Miso.Prelude
import Miso.String qualified as MisoString

class ToGraphQL v where
    toGraphQL :: v -> Value
    default toGraphQL :: (ToJSON v) => v -> Value
    toGraphQL = Value -> Value
forall v. ToGraphQL v => v -> Value
toGraphQL (Value -> Value) -> (v -> Value) -> v -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. v -> Value
forall a. ToJSON a => a -> Value
toJSON

instance ToGraphQL JSON.Value where
    toGraphQL :: Value -> Value
toGraphQL (JSON.Number Double
n) = Double -> Value
forall v. ToGraphQL v => v -> Value
toGraphQL Double
n
    toGraphQL (JSON.Bool Bool
b) = Bool -> Value
forall v. ToGraphQL v => v -> Value
toGraphQL Bool
b
    toGraphQL (JSON.String MisoString
s) = MisoString -> Value
forall v. ToGraphQL v => v -> Value
toGraphQL MisoString
s
    toGraphQL (JSON.Array [Value]
xs) = [Value] -> Value
forall v. ToGraphQL v => v -> Value
toGraphQL [Value]
xs
    toGraphQL (JSON.Object Map MisoString Value
o) = Map MisoString Value -> Value
forall v. ToGraphQL v => v -> Value
toGraphQL Map MisoString Value
o
    toGraphQL Value
JSON.Null = Value
ValueNull

instance (ToGraphQL v) => ToGraphQL [v] where
    toGraphQL :: [v] -> Value
toGraphQL = [Value] -> Value
ValueList ([Value] -> Value) -> ([v] -> [Value]) -> [v] -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (v -> Value) -> [v] -> [Value]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap v -> Value
forall v. ToGraphQL v => v -> Value
toGraphQL

instance (ToGraphQL v) => ToGraphQL (NonEmpty v) where
    toGraphQL :: NonEmpty v -> Value
toGraphQL = [v] -> Value
forall v. ToGraphQL v => v -> Value
toGraphQL ([v] -> Value) -> (NonEmpty v -> [v]) -> NonEmpty v -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. NonEmpty v -> [v]
forall a. NonEmpty a -> [a]
NonEmpty.toList

instance (ToGraphQL v) => ToGraphQL (Maybe v) where
    toGraphQL :: Maybe v -> Value
toGraphQL = Value -> (v -> Value) -> Maybe v -> Value
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Value
ValueNull v -> Value
forall v. ToGraphQL v => v -> Value
toGraphQL

instance (ToGraphQL v) => ToGraphQL (Map MisoString v) where
    toGraphQL :: Map MisoString v -> Value
toGraphQL =
        [ObjectField] -> Value
ValueObject ([ObjectField] -> Value)
-> (Map MisoString v -> [ObjectField]) -> Map MisoString v -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ((MisoString, v) -> ObjectField)
-> [(MisoString, v)] -> [ObjectField]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(MisoString
k, v
v) -> Name -> Value -> ObjectField
ObjectField (MisoString -> Name
Name MisoString
k) (v -> Value
forall v. ToGraphQL v => v -> Value
toGraphQL v
v)) ([(MisoString, v)] -> [ObjectField])
-> (Map MisoString v -> [(MisoString, v)])
-> Map MisoString v
-> [ObjectField]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Map MisoString v -> [(MisoString, v)]
forall k a. Map k a -> [(k, a)]
Map.toList

instance ToGraphQL Int where
    toGraphQL :: Int -> Value
toGraphQL = Int -> Value
ValueInt

instance ToGraphQL Float where
    toGraphQL :: Float -> Value
toGraphQL = Double -> Value
ValueFloat (Double -> Value) -> (Float -> Double) -> Float -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Float -> Double
float2Double

instance ToGraphQL Double where
    toGraphQL :: Double -> Value
toGraphQL = Double -> Value
ValueFloat

instance ToGraphQL MisoString where
    toGraphQL :: MisoString -> Value
toGraphQL MisoString
s
        | Maybe Char -> Bool
forall a. Maybe a -> Bool
isJust (Maybe Char -> Bool)
-> (MisoString -> Maybe Char) -> MisoString -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Char -> Bool) -> MisoString -> Maybe Char
MisoString.find (Char -> [Char] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
'\r', Char
'\n']) (MisoString -> Bool) -> MisoString -> Bool
forall a b. (a -> b) -> a -> b
$ MisoString
s =
            StringValue -> Value
ValueString (StringValue -> Value) -> StringValue -> Value
forall a b. (a -> b) -> a -> b
$ MisoString -> StringValue
BlockString MisoString
s
        | Bool
otherwise = StringValue -> Value
ValueString (StringValue -> Value) -> StringValue -> Value
forall a b. (a -> b) -> a -> b
$ MisoString -> StringValue
SingleLineString MisoString
s

instance ToGraphQL Bool where
    toGraphQL :: Bool -> Value
toGraphQL = Bool -> Value
ValueBoolean