content: module Rattletrap.Type.Attribute.RigidBodyState where
  
  import qualified Rattletrap.BitGet as BitGet
  import qualified Rattletrap.BitPut as BitPut
  import qualified Rattletrap.Schema as Schema
  import qualified Rattletrap.Type.Rotation as Rotation
  import qualified Rattletrap.Type.Vector as Vector
  import qualified Rattletrap.Type.Version as Version
  import qualified Rattletrap.Utility.Json as Json
  import qualified Rattletrap.Utility.Monad as Monad
  
  data RigidBodyState = RigidBodyState
    { sleeping :: Bool,
      location :: Vector.Vector,
      rotation :: Rotation.Rotation,
      linearVelocity :: Maybe Vector.Vector,
      angularVelocity :: Maybe Vector.Vector
    }
    deriving (Eq, Show)
  
  instance Json.FromJSON RigidBodyState where
    parseJSON = Json.withObject "RigidBodyState" $ \object -> do
      sleeping <- Json.required object "sleeping"
      location <- Json.required object "location"
      rotation <- Json.required object "rotation"
      linearVelocity <- Json.optional object "linear_velocity"
      angularVelocity <- Json.optional object "angular_velocity"
      pure
        RigidBodyState
          { sleeping,
            location,
            rotation,
            linearVelocity,
            angularVelocity
          }
  
  instance Json.ToJSON RigidBodyState where
    toJSON x =
      Json.object
        [ Json.pair "sleeping" $ sleeping x,
          Json.pair "location" $ location x,
          Json.pair "rotation" $ rotation x,
          Json.pair "linear_velocity" $ linearVelocity x,
          Json.pair "angular_velocity" $ angularVelocity x
        ]
  
  schema :: Schema.Schema
  schema =
    Schema.named "attribute-rigid-body-state" $
      Schema.object
        [ (Json.pair "sleeping" $ Schema.ref Schema.boolean, True),
          (Json.pair "location" $ Schema.ref Vector.schema, True),
          (Json.pair "rotation" $ Schema.ref Rotation.schema, True),
          ( Json.pair "linear_velocity" . Schema.json $ Schema.maybe Vector.schema,
            False
          ),
          ( Json.pair "angular_velocity" . Schema.json $ Schema.maybe Vector.schema,
            False
          )
        ]
  
  bitPut :: RigidBodyState -> BitPut.BitPut
  bitPut rigidBodyStateAttribute =
    BitPut.bool (sleeping rigidBodyStateAttribute)
      <> Vector.bitPut (location rigidBodyStateAttribute)
      <> Rotation.bitPut (rotation rigidBodyStateAttribute)
      <> foldMap Vector.bitPut (linearVelocity rigidBodyStateAttribute)
      <> foldMap Vector.bitPut (angularVelocity rigidBodyStateAttribute)
  
  bitGet :: Version.Version -> BitGet.BitGet RigidBodyState
  bitGet version = BitGet.label "RigidBodyState" $ do
    sleeping <- BitGet.label "sleeping" BitGet.bool
    location <- BitGet.label "location" $ Vector.bitGet version
    rotation <- BitGet.label "rotation" $ Rotation.bitGet version
    linearVelocity <-
      BitGet.label "linearVelocity" $
        Monad.whenMaybe (not sleeping) (Vector.bitGet version)
    angularVelocity <-
      BitGet.label "angularVelocity" $
        Monad.whenMaybe (not sleeping) (Vector.bitGet version)
    pure
      RigidBodyState
        { sleeping,
          location,
          rotation,
          linearVelocity,
          angularVelocity
        }
  