module Rattletrap.Type.Attribute.ProductValue where import qualified Data.Foldable as Foldable import qualified Data.Word as Word import qualified Rattletrap.BitGet as BitGet import qualified Rattletrap.BitPut as BitPut import qualified Rattletrap.Exception.MissingProductName as MissingProductName import qualified Rattletrap.Exception.UnknownProduct as UnknownProduct import qualified Rattletrap.Schema as Schema import qualified Rattletrap.Type.CompressedWord as CompressedWord 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 data ProductValue = PaintedOld CompressedWord.CompressedWord | PaintedNew Word.Word32 | TeamEditionOld CompressedWord.CompressedWord | TeamEditionNew Word.Word32 | SpecialEdition Word.Word32 | UserColorOld (Maybe Word.Word32) | UserColorNew U32.U32 | TitleId Str.Str deriving (Eq, Show) instance Json.FromJSON ProductValue where parseJSON = Json.withObject "ProductValue" $ \object -> Foldable.asum [ fmap PaintedOld $ Json.required object "painted_old" , fmap PaintedNew $ Json.required object "painted_new" , fmap TeamEditionOld $ Json.required object "team_edition_old" , fmap TeamEditionNew $ Json.required object "team_edition_new" , fmap SpecialEdition $ Json.required object "special_edition" , fmap UserColorOld $ Json.required object "user_color_old" , fmap UserColorNew $ Json.required object "user_color_new" , fmap TitleId $ Json.required object "title_id" ] instance Json.ToJSON ProductValue where toJSON x = case x of PaintedOld y -> Json.object [Json.pair "painted_old" y] PaintedNew y -> Json.object [Json.pair "painted_new" y] TeamEditionOld y -> Json.object [Json.pair "team_edition_old" y] TeamEditionNew y -> Json.object [Json.pair "team_edition_new" y] SpecialEdition y -> Json.object [Json.pair "special_edition" y] UserColorOld y -> Json.object [Json.pair "user_color_old" y] UserColorNew y -> Json.object [Json.pair "user_color_new" y] TitleId y -> Json.object [Json.pair "title_id" y] schema :: Schema.Schema schema = Schema.named "attribute-product-value" . Schema.oneOf $ fmap (\(k, v) -> Schema.object [(Json.pair k v, True)]) [ ("painted_old", Schema.ref CompressedWord.schema) , ("painted_new", Schema.ref Schema.integer) , ("team_edition_old", Schema.ref CompressedWord.schema) , ("team_edition_new", Schema.ref Schema.integer) , ("special_edition", Schema.ref Schema.integer) , ("user_color_old", Schema.json $ Schema.maybe Schema.integer) , ("user_color_new", Schema.ref U32.schema) , ("title_id", Schema.ref Str.schema) ] bitPut :: ProductValue -> BitPut.BitPut bitPut val = case val of PaintedOld x -> CompressedWord.bitPut x PaintedNew x -> BitPut.bits 31 x TeamEditionOld x -> CompressedWord.bitPut x TeamEditionNew x -> BitPut.bits 31 x SpecialEdition x -> BitPut.bits 31 x UserColorOld x -> case x of Nothing -> BitPut.bool False Just y -> BitPut.bool True <> BitPut.bits 31 y UserColorNew x -> U32.bitPut x TitleId x -> Str.bitPut x bitGet :: Version.Version -> U32.U32 -> Maybe Str.Str -> BitGet.BitGet ProductValue bitGet version objectId maybeObjectName = BitGet.label "ProductValue" $ case fmap Str.toString maybeObjectName of Just "TAGame.ProductAttribute_Painted_TA" -> decodePainted version Just "TAGame.ProductAttribute_SpecialEdition_TA" -> decodeSpecialEdition Just "TAGame.ProductAttribute_TeamEdition_TA" -> decodeTeamEdition version Just "TAGame.ProductAttribute_TitleID_TA" -> decodeTitle Just "TAGame.ProductAttribute_UserColor_TA" -> decodeColor version Just x -> BitGet.throw $ UnknownProduct.UnknownProduct x Nothing -> BitGet.throw . MissingProductName.MissingProductName $ U32.toWord32 objectId decodeSpecialEdition :: BitGet.BitGet ProductValue decodeSpecialEdition = BitGet.label "SpecialEdition" . fmap SpecialEdition $ BitGet.bits 31 decodePainted :: Version.Version -> BitGet.BitGet ProductValue decodePainted version = BitGet.label "Painted" $ if hasNewPainted version then fmap PaintedNew $ BitGet.bits 31 else fmap PaintedOld $ CompressedWord.bitGet 13 decodeTeamEdition :: Version.Version -> BitGet.BitGet ProductValue decodeTeamEdition version = BitGet.label "TeamEdition" $ if hasNewPainted version then fmap TeamEditionNew $ BitGet.bits 31 else fmap TeamEditionOld $ CompressedWord.bitGet 13 decodeColor :: Version.Version -> BitGet.BitGet ProductValue decodeColor version = BitGet.label "UserColor" $ if Version.atLeast 868 23 8 version then fmap UserColorNew U32.bitGet else do hasValue <- BitGet.bool fmap UserColorOld $ Monad.whenMaybe hasValue (BitGet.bits 31) hasNewPainted :: Version.Version -> Bool hasNewPainted = Version.atLeast 868 18 0 decodeTitle :: BitGet.BitGet ProductValue decodeTitle = BitGet.label "Title" $ fmap TitleId Str.bitGet