module Rattletrap.Decode.Attribute
  ( decodeAttributesBits
  )
where

import Rattletrap.Decode.AttributeValue
import Rattletrap.Decode.Common
import Rattletrap.Decode.CompressedWord
import Rattletrap.Type.Attribute
import Rattletrap.Type.ClassAttributeMap
import Rattletrap.Type.Common
import Rattletrap.Type.CompressedWord
import Rattletrap.Type.Str
import Rattletrap.Type.Word32le

decodeAttributesBits
  :: (Int, Int, Int)
  -> ClassAttributeMap
  -> Map CompressedWord Word32le
  -> CompressedWord
  -> DecodeBits [Attribute]
decodeAttributesBits :: (Int, Int, Int)
-> ClassAttributeMap
-> Map CompressedWord Word32le
-> CompressedWord
-> DecodeBits [Attribute]
decodeAttributesBits (Int, Int, Int)
version ClassAttributeMap
classes Map CompressedWord Word32le
actors CompressedWord
actor = do
  Bool
hasAttribute <- BitGet Bool
getBool
  if Bool
hasAttribute
    then
      (:)
      (Attribute -> [Attribute] -> [Attribute])
-> BitGet Attribute -> BitGet ([Attribute] -> [Attribute])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int, Int, Int)
-> ClassAttributeMap
-> Map CompressedWord Word32le
-> CompressedWord
-> BitGet Attribute
decodeAttributeBits (Int, Int, Int)
version ClassAttributeMap
classes Map CompressedWord Word32le
actors CompressedWord
actor
      BitGet ([Attribute] -> [Attribute])
-> DecodeBits [Attribute] -> DecodeBits [Attribute]
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Int, Int, Int)
-> ClassAttributeMap
-> Map CompressedWord Word32le
-> CompressedWord
-> DecodeBits [Attribute]
decodeAttributesBits (Int, Int, Int)
version ClassAttributeMap
classes Map CompressedWord Word32le
actors CompressedWord
actor
    else [Attribute] -> DecodeBits [Attribute]
forall (f :: * -> *) a. Applicative f => a -> f a
pure []

decodeAttributeBits
  :: (Int, Int, Int)
  -> ClassAttributeMap
  -> Map CompressedWord Word32le
  -> CompressedWord
  -> DecodeBits Attribute
decodeAttributeBits :: (Int, Int, Int)
-> ClassAttributeMap
-> Map CompressedWord Word32le
-> CompressedWord
-> BitGet Attribute
decodeAttributeBits (Int, Int, Int)
version ClassAttributeMap
classes Map CompressedWord Word32le
actors CompressedWord
actor = do
  Map Word32le Word32le
attributes <- ClassAttributeMap
-> Map CompressedWord Word32le
-> CompressedWord
-> DecodeBits (Map Word32le Word32le)
lookupAttributeMap ClassAttributeMap
classes Map CompressedWord Word32le
actors CompressedWord
actor
  Word
limit <- Map Word32le Word32le -> CompressedWord -> DecodeBits Word
lookupAttributeIdLimit Map Word32le Word32le
attributes CompressedWord
actor
  CompressedWord
attribute <- Word -> DecodeBits CompressedWord
decodeCompressedWordBits Word
limit
  Str
name <- ClassAttributeMap
-> Map Word32le Word32le -> CompressedWord -> DecodeBits Str
lookupAttributeName ClassAttributeMap
classes Map Word32le Word32le
attributes CompressedWord
attribute
  CompressedWord -> Str -> AttributeValue -> Attribute
Attribute CompressedWord
attribute Str
name
    (AttributeValue -> Attribute)
-> BitGet AttributeValue -> BitGet Attribute
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int, Int, Int) -> Map Word32le Str -> Str -> BitGet AttributeValue
decodeAttributeValueBits
          (Int, Int, Int)
version
          (ClassAttributeMap -> Map Word32le Str
classAttributeMapObjectMap ClassAttributeMap
classes)
          Str
name

lookupAttributeMap
  :: ClassAttributeMap
  -> Map CompressedWord Word32le
  -> CompressedWord
  -> DecodeBits (Map Word32le Word32le)
lookupAttributeMap :: ClassAttributeMap
-> Map CompressedWord Word32le
-> CompressedWord
-> DecodeBits (Map Word32le Word32le)
lookupAttributeMap ClassAttributeMap
classes Map CompressedWord Word32le
actors CompressedWord
actor = String
-> Maybe (Map Word32le Word32le)
-> DecodeBits (Map Word32le Word32le)
forall a. String -> Maybe a -> DecodeBits a
fromMaybe
  (String
"[RT01] could not get attribute map for " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> CompressedWord -> String
forall a. Show a => a -> String
show CompressedWord
actor)
  (ClassAttributeMap
-> Map CompressedWord Word32le
-> CompressedWord
-> Maybe (Map Word32le Word32le)
getAttributeMap ClassAttributeMap
classes Map CompressedWord Word32le
actors CompressedWord
actor)

lookupAttributeIdLimit
  :: Map Word32le Word32le -> CompressedWord -> DecodeBits Word
lookupAttributeIdLimit :: Map Word32le Word32le -> CompressedWord -> DecodeBits Word
lookupAttributeIdLimit Map Word32le Word32le
attributes CompressedWord
actor = String -> Maybe Word -> DecodeBits Word
forall a. String -> Maybe a -> DecodeBits a
fromMaybe
  (String
"[RT02] could not get attribute ID limit for " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> CompressedWord -> String
forall a. Show a => a -> String
show CompressedWord
actor)
  (Map Word32le Word32le -> Maybe Word
getAttributeIdLimit Map Word32le Word32le
attributes)

lookupAttributeName
  :: ClassAttributeMap
  -> Map Word32le Word32le
  -> CompressedWord
  -> DecodeBits Str
lookupAttributeName :: ClassAttributeMap
-> Map Word32le Word32le -> CompressedWord -> DecodeBits Str
lookupAttributeName ClassAttributeMap
classes Map Word32le Word32le
attributes CompressedWord
attribute = String -> Maybe Str -> DecodeBits Str
forall a. String -> Maybe a -> DecodeBits a
fromMaybe
  (String
"[RT03] could not get attribute name for " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> CompressedWord -> String
forall a. Show a => a -> String
show CompressedWord
attribute)
  (ClassAttributeMap
-> Map Word32le Word32le -> CompressedWord -> Maybe Str
getAttributeName ClassAttributeMap
classes Map Word32le Word32le
attributes CompressedWord
attribute)

fromMaybe :: String -> Maybe a -> DecodeBits a
fromMaybe :: String -> Maybe a -> DecodeBits a
fromMaybe String
message = DecodeBits a -> (a -> DecodeBits a) -> Maybe a -> DecodeBits a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> DecodeBits a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
message) a -> DecodeBits a
forall (f :: * -> *) a. Applicative f => a -> f a
pure