module Rattletrap.Type.Frame 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.F32 as F32
import qualified Rattletrap.Type.List as List
import qualified Rattletrap.Type.Replication as Replication
import qualified Rattletrap.Type.U32 as U32
import qualified Rattletrap.Type.Version as Version
import qualified Rattletrap.Utility.Json as Json

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

data Frame = Frame
  { Frame -> F32
time :: F32.F32
  -- ^ Time in seconds since the beginning of the match.
  , Frame -> F32
delta :: F32.F32
  -- ^ Time in seconds since the last frame. Usually about 0.03 since there
  -- are 30 frames per second.
  , Frame -> List Replication
replications :: List.List Replication.Replication
  }
  deriving (Frame -> Frame -> Bool
(Frame -> Frame -> Bool) -> (Frame -> Frame -> Bool) -> Eq Frame
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Frame -> Frame -> Bool
$c/= :: Frame -> Frame -> Bool
== :: Frame -> Frame -> Bool
$c== :: Frame -> Frame -> Bool
Eq, Int -> Frame -> ShowS
[Frame] -> ShowS
Frame -> String
(Int -> Frame -> ShowS)
-> (Frame -> String) -> ([Frame] -> ShowS) -> Show Frame
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Frame] -> ShowS
$cshowList :: [Frame] -> ShowS
show :: Frame -> String
$cshow :: Frame -> String
showsPrec :: Int -> Frame -> ShowS
$cshowsPrec :: Int -> Frame -> ShowS
Show)

instance Json.FromJSON Frame where
  parseJSON :: Value -> Parser Frame
parseJSON = String -> (Object -> Parser Frame) -> Value -> Parser Frame
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Json.withObject String
"Frame" ((Object -> Parser Frame) -> Value -> Parser Frame)
-> (Object -> Parser Frame) -> Value -> Parser Frame
forall a b. (a -> b) -> a -> b
$ \Object
object -> do
    F32
time <- Object -> String -> Parser F32
forall value. FromJSON value => Object -> String -> Parser value
Json.required Object
object String
"time"
    F32
delta <- Object -> String -> Parser F32
forall value. FromJSON value => Object -> String -> Parser value
Json.required Object
object String
"delta"
    List Replication
replications <- Object -> String -> Parser (List Replication)
forall value. FromJSON value => Object -> String -> Parser value
Json.required Object
object String
"replications"
    Frame -> Parser Frame
forall (f :: * -> *) a. Applicative f => a -> f a
pure Frame :: F32 -> F32 -> List Replication -> Frame
Frame { F32
time :: F32
time :: F32
time, F32
delta :: F32
delta :: F32
delta, List Replication
replications :: List Replication
replications :: List Replication
replications }

instance Json.ToJSON Frame where
  toJSON :: Frame -> Value
toJSON Frame
x = [Pair] -> Value
Json.object
    [ String -> F32 -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"time" (F32 -> Pair) -> F32 -> Pair
forall a b. (a -> b) -> a -> b
$ Frame -> F32
time Frame
x
    , String -> F32 -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"delta" (F32 -> Pair) -> F32 -> Pair
forall a b. (a -> b) -> a -> b
$ Frame -> F32
delta Frame
x
    , String -> List Replication -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"replications" (List Replication -> Pair) -> List Replication -> Pair
forall a b. (a -> b) -> a -> b
$ Frame -> List Replication
replications Frame
x
    ]

schema :: Schema.Schema
schema :: Schema
schema = String -> Value -> Schema
Schema.named String
"frame" (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
"time" (Value -> Pair) -> Value -> Pair
forall a b. (a -> b) -> a -> b
$ Schema -> Value
Schema.ref Schema
F32.schema, Bool
True)
  , (String -> Value -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"delta" (Value -> Pair) -> Value -> Pair
forall a b. (a -> b) -> a -> b
$ Schema -> Value
Schema.ref Schema
F32.schema, Bool
True)
  , ( String -> Value -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"replications" (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
List.schema Schema
Replication.schema
    , Bool
True
    )
  ]

putFrames :: List.List Frame -> BitPut.BitPut
putFrames :: List Frame -> BitPut
putFrames = (Frame -> BitPut) -> [Frame] -> BitPut
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Frame -> BitPut
bitPut ([Frame] -> BitPut)
-> (List Frame -> [Frame]) -> List Frame -> BitPut
forall b c a. (b -> c) -> (a -> b) -> a -> c
. List Frame -> [Frame]
forall a. List a -> [a]
List.toList

bitPut :: Frame -> BitPut.BitPut
bitPut :: Frame -> BitPut
bitPut Frame
frame =
  F32 -> BitPut
F32.bitPut (Frame -> F32
time Frame
frame)
    BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> F32 -> BitPut
F32.bitPut (Frame -> F32
delta Frame
frame)
    BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> List Replication -> BitPut
Replication.putReplications (Frame -> List Replication
replications Frame
frame)

decodeFramesBits
  :: Version.Version
  -> Int
  -> Word
  -> ClassAttributeMap.ClassAttributeMap
  -> State.StateT
       (Map.Map CompressedWord.CompressedWord U32.U32)
       BitGet.BitGet
       (List.List Frame)
decodeFramesBits :: Version
-> Int
-> Word
-> ClassAttributeMap
-> StateT (Map CompressedWord U32) BitGet (List Frame)
decodeFramesBits Version
version Int
count Word
limit ClassAttributeMap
classes =
  Int
-> StateT (Map CompressedWord U32) BitGet Frame
-> StateT (Map CompressedWord U32) BitGet (List Frame)
forall (m :: * -> *) a. Monad m => Int -> m a -> m (List a)
List.replicateM Int
count (StateT (Map CompressedWord U32) BitGet Frame
 -> StateT (Map CompressedWord U32) BitGet (List Frame))
-> StateT (Map CompressedWord U32) BitGet Frame
-> StateT (Map CompressedWord U32) BitGet (List Frame)
forall a b. (a -> b) -> a -> b
$ Version
-> Word
-> ClassAttributeMap
-> StateT (Map CompressedWord U32) BitGet Frame
bitGet Version
version Word
limit ClassAttributeMap
classes

bitGet
  :: Version.Version
  -> Word
  -> ClassAttributeMap.ClassAttributeMap
  -> State.StateT
       (Map.Map CompressedWord.CompressedWord U32.U32)
       BitGet.BitGet
       Frame
bitGet :: Version
-> Word
-> ClassAttributeMap
-> StateT (Map CompressedWord U32) BitGet Frame
bitGet Version
version Word
limit ClassAttributeMap
classes =
  F32 -> F32 -> List Replication -> Frame
Frame
    (F32 -> F32 -> List Replication -> Frame)
-> StateT (Map CompressedWord U32) BitGet F32
-> StateT
     (Map CompressedWord U32) BitGet (F32 -> List Replication -> Frame)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BitGet F32 -> StateT (Map CompressedWord U32) BitGet F32
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
Trans.lift BitGet F32
F32.bitGet
    StateT
  (Map CompressedWord U32) BitGet (F32 -> List Replication -> Frame)
-> StateT (Map CompressedWord U32) BitGet F32
-> StateT
     (Map CompressedWord U32) BitGet (List Replication -> Frame)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> BitGet F32 -> StateT (Map CompressedWord U32) BitGet F32
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
Trans.lift BitGet F32
F32.bitGet
    StateT (Map CompressedWord U32) BitGet (List Replication -> Frame)
-> StateT (Map CompressedWord U32) BitGet (List Replication)
-> StateT (Map CompressedWord U32) BitGet Frame
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Version
-> Word
-> ClassAttributeMap
-> StateT (Map CompressedWord U32) BitGet (List Replication)
Replication.decodeReplicationsBits Version
version Word
limit ClassAttributeMap
classes