module Rattletrap.Type.Replication where

import qualified Rattletrap.BitGet as BitGet
import qualified Rattletrap.BitPut as BitPut
import qualified Rattletrap.Schema as Schema
import qualified Rattletrap.Type.ClassAttributeMap as ClassAttributeMap
import qualified Rattletrap.Type.CompressedWord as CompressedWord
import qualified Rattletrap.Type.List as List
import qualified Rattletrap.Type.ReplicationValue as ReplicationValue
import qualified Rattletrap.Type.Str as Str
import qualified Rattletrap.Type.U32 as U32
import qualified Rattletrap.Type.Version as Version
import qualified Rattletrap.Utility.Json as Json
import qualified Rattletrap.Utility.Monad as Monad

import qualified Control.Monad.Trans.Class as Trans
import qualified Control.Monad.Trans.State as State
import qualified Data.Map as Map

data Replication = Replication
  { Replication -> CompressedWord
actorId :: CompressedWord.CompressedWord
  , Replication -> ReplicationValue
value :: ReplicationValue.ReplicationValue
  }
  deriving (Replication -> Replication -> Bool
(Replication -> Replication -> Bool)
-> (Replication -> Replication -> Bool) -> Eq Replication
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Replication -> Replication -> Bool
$c/= :: Replication -> Replication -> Bool
== :: Replication -> Replication -> Bool
$c== :: Replication -> Replication -> Bool
Eq, Int -> Replication -> ShowS
[Replication] -> ShowS
Replication -> String
(Int -> Replication -> ShowS)
-> (Replication -> String)
-> ([Replication] -> ShowS)
-> Show Replication
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Replication] -> ShowS
$cshowList :: [Replication] -> ShowS
show :: Replication -> String
$cshow :: Replication -> String
showsPrec :: Int -> Replication -> ShowS
$cshowsPrec :: Int -> Replication -> ShowS
Show)

instance Json.FromJSON Replication where
  parseJSON :: Value -> Parser Replication
parseJSON = String
-> (Object -> Parser Replication) -> Value -> Parser Replication
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Json.withObject String
"Replication" ((Object -> Parser Replication) -> Value -> Parser Replication)
-> (Object -> Parser Replication) -> Value -> Parser Replication
forall a b. (a -> b) -> a -> b
$ \Object
object -> do
    CompressedWord
actorId <- Object -> String -> Parser CompressedWord
forall value. FromJSON value => Object -> String -> Parser value
Json.required Object
object String
"actor_id"
    ReplicationValue
value <- Object -> String -> Parser ReplicationValue
forall value. FromJSON value => Object -> String -> Parser value
Json.required Object
object String
"value"
    Replication -> Parser Replication
forall (f :: * -> *) a. Applicative f => a -> f a
pure Replication :: CompressedWord -> ReplicationValue -> Replication
Replication { CompressedWord
actorId :: CompressedWord
actorId :: CompressedWord
actorId, ReplicationValue
value :: ReplicationValue
value :: ReplicationValue
value }

instance Json.ToJSON Replication where
  toJSON :: Replication -> Value
toJSON Replication
x =
    [Pair] -> Value
Json.object [String -> CompressedWord -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"actor_id" (CompressedWord -> Pair) -> CompressedWord -> Pair
forall a b. (a -> b) -> a -> b
$ Replication -> CompressedWord
actorId Replication
x, String -> ReplicationValue -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"value" (ReplicationValue -> Pair) -> ReplicationValue -> Pair
forall a b. (a -> b) -> a -> b
$ Replication -> ReplicationValue
value Replication
x]

schema :: Schema.Schema
schema :: Schema
schema = String -> Value -> Schema
Schema.named String
"replication" (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
"actor_id" (Value -> Pair) -> Value -> Pair
forall a b. (a -> b) -> a -> b
$ Schema -> Value
Schema.ref Schema
CompressedWord.schema, Bool
True)
  , (String -> Value -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"value" (Value -> Pair) -> Value -> Pair
forall a b. (a -> b) -> a -> b
$ Schema -> Value
Schema.ref Schema
ReplicationValue.schema, Bool
True)
  ]

putReplications :: List.List Replication -> BitPut.BitPut
putReplications :: List Replication -> BitPut
putReplications List Replication
xs =
  (Replication -> BitPut) -> [Replication] -> BitPut
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (\Replication
x -> Bool -> BitPut
BitPut.bool Bool
True BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> Replication -> BitPut
bitPut Replication
x) (List Replication -> [Replication]
forall a. List a -> [a]
List.toList List Replication
xs)
    BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> Bool -> BitPut
BitPut.bool Bool
False

bitPut :: Replication -> BitPut.BitPut
bitPut :: Replication -> BitPut
bitPut Replication
replication = CompressedWord -> BitPut
CompressedWord.bitPut (Replication -> CompressedWord
actorId Replication
replication)
  BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> ReplicationValue -> BitPut
ReplicationValue.bitPut (Replication -> ReplicationValue
value Replication
replication)

decodeReplicationsBits
  :: Maybe Str.Str
  -> Version.Version
  -> Word
  -> ClassAttributeMap.ClassAttributeMap
  -> State.StateT
       (Map.Map CompressedWord.CompressedWord U32.U32)
       BitGet.BitGet
       (List.List Replication)
decodeReplicationsBits :: Maybe Str
-> Version
-> Word
-> ClassAttributeMap
-> StateT (Map CompressedWord U32) BitGet (List Replication)
decodeReplicationsBits Maybe Str
matchType Version
version Word
limit ClassAttributeMap
classes = StateT (Map CompressedWord U32) BitGet (Maybe Replication)
-> StateT (Map CompressedWord U32) BitGet (List Replication)
forall (m :: * -> *) a. Monad m => m (Maybe a) -> m (List a)
List.untilM (StateT (Map CompressedWord U32) BitGet (Maybe Replication)
 -> StateT (Map CompressedWord U32) BitGet (List Replication))
-> StateT (Map CompressedWord U32) BitGet (Maybe Replication)
-> StateT (Map CompressedWord U32) BitGet (List Replication)
forall a b. (a -> b) -> a -> b
$ do
  Bool
p <- Get BitString Identity Bool
-> StateT (Map CompressedWord U32) BitGet Bool
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
Trans.lift Get BitString Identity Bool
BitGet.bool
  Bool
-> StateT (Map CompressedWord U32) BitGet Replication
-> StateT (Map CompressedWord U32) BitGet (Maybe Replication)
forall (m :: * -> *) a. Applicative m => Bool -> m a -> m (Maybe a)
Monad.whenMaybe Bool
p (StateT (Map CompressedWord U32) BitGet Replication
 -> StateT (Map CompressedWord U32) BitGet (Maybe Replication))
-> StateT (Map CompressedWord U32) BitGet Replication
-> StateT (Map CompressedWord U32) BitGet (Maybe Replication)
forall a b. (a -> b) -> a -> b
$ Maybe Str
-> Version
-> Word
-> ClassAttributeMap
-> StateT (Map CompressedWord U32) BitGet Replication
bitGet Maybe Str
matchType Version
version Word
limit ClassAttributeMap
classes

bitGet
  :: Maybe Str.Str
  -> Version.Version
  -> Word
  -> ClassAttributeMap.ClassAttributeMap
  -> State.StateT
       (Map.Map CompressedWord.CompressedWord U32.U32)
       BitGet.BitGet
       Replication
bitGet :: Maybe Str
-> Version
-> Word
-> ClassAttributeMap
-> StateT (Map CompressedWord U32) BitGet Replication
bitGet Maybe Str
matchType Version
version Word
limit ClassAttributeMap
classes = do
  CompressedWord
actor <- Get BitString Identity CompressedWord
-> StateT (Map CompressedWord U32) BitGet CompressedWord
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
Trans.lift (Word -> Get BitString Identity CompressedWord
CompressedWord.bitGet Word
limit)
  (ReplicationValue -> Replication)
-> StateT (Map CompressedWord U32) BitGet ReplicationValue
-> StateT (Map CompressedWord U32) BitGet Replication
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (CompressedWord -> ReplicationValue -> Replication
Replication CompressedWord
actor)
    (StateT (Map CompressedWord U32) BitGet ReplicationValue
 -> StateT (Map CompressedWord U32) BitGet Replication)
-> StateT (Map CompressedWord U32) BitGet ReplicationValue
-> StateT (Map CompressedWord U32) BitGet Replication
forall a b. (a -> b) -> a -> b
$ Maybe Str
-> Version
-> ClassAttributeMap
-> CompressedWord
-> StateT (Map CompressedWord U32) BitGet ReplicationValue
ReplicationValue.bitGet Maybe Str
matchType Version
version ClassAttributeMap
classes CompressedWord
actor