module Rattletrap.Type.Initialization where

import qualified Rattletrap.BitGet as BitGet
import qualified Rattletrap.BitPut as BitPut
import qualified Rattletrap.Schema as Schema
import qualified Rattletrap.Type.Int8Vector as Int8Vector
import qualified Rattletrap.Type.Vector as Vector
import qualified Rattletrap.Type.Version as Version
import qualified Rattletrap.Utility.Json as Json
import Rattletrap.Utility.Monad

data Initialization = Initialization
  { Initialization -> Maybe Vector
location :: Maybe Vector.Vector
  -- ^ Not every class has an initial location. See
  -- 'Rattletrap.Data.classesWithLocation'.
  , Initialization -> Maybe Int8Vector
rotation :: Maybe Int8Vector.Int8Vector
  -- ^ Only classes with location can have rotation, but not every one does.
  -- See 'Rattletrap.Data.classesWithRotation'.
  }
  deriving (Initialization -> Initialization -> Bool
(Initialization -> Initialization -> Bool)
-> (Initialization -> Initialization -> Bool) -> Eq Initialization
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Initialization -> Initialization -> Bool
$c/= :: Initialization -> Initialization -> Bool
== :: Initialization -> Initialization -> Bool
$c== :: Initialization -> Initialization -> Bool
Eq, Int -> Initialization -> ShowS
[Initialization] -> ShowS
Initialization -> String
(Int -> Initialization -> ShowS)
-> (Initialization -> String)
-> ([Initialization] -> ShowS)
-> Show Initialization
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Initialization] -> ShowS
$cshowList :: [Initialization] -> ShowS
show :: Initialization -> String
$cshow :: Initialization -> String
showsPrec :: Int -> Initialization -> ShowS
$cshowsPrec :: Int -> Initialization -> ShowS
Show)

instance Json.FromJSON Initialization where
  parseJSON :: Value -> Parser Initialization
parseJSON = String
-> (Object -> Parser Initialization)
-> Value
-> Parser Initialization
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Json.withObject String
"Initialization" ((Object -> Parser Initialization)
 -> Value -> Parser Initialization)
-> (Object -> Parser Initialization)
-> Value
-> Parser Initialization
forall a b. (a -> b) -> a -> b
$ \Object
object -> do
    Maybe Vector
location <- Object -> String -> Parser (Maybe Vector)
forall value.
FromJSON value =>
Object -> String -> Parser (Maybe value)
Json.optional Object
object String
"location"
    Maybe Int8Vector
rotation <- Object -> String -> Parser (Maybe Int8Vector)
forall value.
FromJSON value =>
Object -> String -> Parser (Maybe value)
Json.optional Object
object String
"rotation"
    Initialization -> Parser Initialization
forall (f :: * -> *) a. Applicative f => a -> f a
pure Initialization :: Maybe Vector -> Maybe Int8Vector -> Initialization
Initialization { Maybe Vector
location :: Maybe Vector
location :: Maybe Vector
location, Maybe Int8Vector
rotation :: Maybe Int8Vector
rotation :: Maybe Int8Vector
rotation }

instance Json.ToJSON Initialization where
  toJSON :: Initialization -> Value
toJSON Initialization
x = [Pair] -> Value
Json.object
    [String -> Maybe Vector -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"location" (Maybe Vector -> Pair) -> Maybe Vector -> Pair
forall a b. (a -> b) -> a -> b
$ Initialization -> Maybe Vector
location Initialization
x, String -> Maybe Int8Vector -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"rotation" (Maybe Int8Vector -> Pair) -> Maybe Int8Vector -> Pair
forall a b. (a -> b) -> a -> b
$ Initialization -> Maybe Int8Vector
rotation Initialization
x]

schema :: Schema.Schema
schema :: Schema
schema = String -> Value -> Schema
Schema.named String
"initialization" (Value -> Schema) -> Value -> Schema
forall a b. (a -> b) -> a -> b
$ [(Pair, Bool)] -> Value
Schema.object
  [ (String -> Value -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"location" (Value -> Pair) -> (Schema -> Value) -> Schema -> Pair
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Schema -> Value
Schema.json (Schema -> Pair) -> Schema -> Pair
forall a b. (a -> b) -> a -> b
$ Schema -> Schema
Schema.maybe Schema
Vector.schema, Bool
False)
  , ( String -> Value -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"rotation" (Value -> Pair) -> (Schema -> Value) -> Schema -> Pair
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Schema -> Value
Schema.json (Schema -> Pair) -> Schema -> Pair
forall a b. (a -> b) -> a -> b
$ Schema -> Schema
Schema.maybe Schema
Int8Vector.schema
    , Bool
False
    )
  ]

bitPut :: Initialization -> BitPut.BitPut
bitPut :: Initialization -> BitPut
bitPut Initialization
initialization =
  (Vector -> BitPut) -> Maybe Vector -> BitPut
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Vector -> BitPut
Vector.bitPut (Initialization -> Maybe Vector
location Initialization
initialization)
    BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> (Int8Vector -> BitPut) -> Maybe Int8Vector -> BitPut
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Int8Vector -> BitPut
Int8Vector.bitPut (Initialization -> Maybe Int8Vector
rotation Initialization
initialization)

bitGet :: Version.Version -> Bool -> Bool -> BitGet.BitGet Initialization
bitGet :: Version -> Bool -> Bool -> BitGet Initialization
bitGet Version
version Bool
hasLocation Bool
hasRotation =
  Maybe Vector -> Maybe Int8Vector -> Initialization
Initialization
    (Maybe Vector -> Maybe Int8Vector -> Initialization)
-> BitGet (Maybe Vector)
-> BitGet (Maybe Int8Vector -> Initialization)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Bool -> BitGet Vector -> BitGet (Maybe Vector)
forall (m :: * -> *) a. Applicative m => Bool -> m a -> m (Maybe a)
whenMaybe Bool
hasLocation (Version -> BitGet Vector
Vector.bitGet Version
version)
    BitGet (Maybe Int8Vector -> Initialization)
-> BitGet (Maybe Int8Vector) -> BitGet Initialization
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Bool -> BitGet Int8Vector -> BitGet (Maybe Int8Vector)
forall (m :: * -> *) a. Applicative m => Bool -> m a -> m (Maybe a)
whenMaybe Bool
hasRotation BitGet Int8Vector
Int8Vector.bitGet