module Rattletrap.Type.Attribute.Product where

import qualified Data.Map as Map
import qualified Rattletrap.BitGet as BitGet
import qualified Rattletrap.BitPut as BitPut
import qualified Rattletrap.Schema as Schema
import qualified Rattletrap.Type.Attribute.ProductValue as ProductValue
import qualified Rattletrap.Type.List as List
import qualified Rattletrap.Type.Str as Str
import qualified Rattletrap.Type.U32 as U32
import qualified Rattletrap.Type.U8 as U8
import qualified Rattletrap.Type.Version as Version
import qualified Rattletrap.Utility.Json as Json

data Product = Product
  { Product -> Bool
unknown :: Bool
  , Product -> U32
objectId :: U32.U32
  , Product -> Maybe Str
objectName :: Maybe Str.Str
  -- ^ read-only
  , Product -> ProductValue
value :: ProductValue.ProductValue
  }
  deriving (Product -> Product -> Bool
(Product -> Product -> Bool)
-> (Product -> Product -> Bool) -> Eq Product
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Product -> Product -> Bool
$c/= :: Product -> Product -> Bool
== :: Product -> Product -> Bool
$c== :: Product -> Product -> Bool
Eq, Int -> Product -> ShowS
[Product] -> ShowS
Product -> String
(Int -> Product -> ShowS)
-> (Product -> String) -> ([Product] -> ShowS) -> Show Product
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Product] -> ShowS
$cshowList :: [Product] -> ShowS
show :: Product -> String
$cshow :: Product -> String
showsPrec :: Int -> Product -> ShowS
$cshowsPrec :: Int -> Product -> ShowS
Show)

instance Json.FromJSON Product where
  parseJSON :: Value -> Parser Product
parseJSON = String -> (Object -> Parser Product) -> Value -> Parser Product
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Json.withObject String
"Product" ((Object -> Parser Product) -> Value -> Parser Product)
-> (Object -> Parser Product) -> Value -> Parser Product
forall a b. (a -> b) -> a -> b
$ \Object
object -> do
    Bool
unknown <- Object -> String -> Parser Bool
forall value. FromJSON value => Object -> String -> Parser value
Json.required Object
object String
"unknown"
    U32
objectId <- Object -> String -> Parser U32
forall value. FromJSON value => Object -> String -> Parser value
Json.required Object
object String
"object_id"
    Maybe Str
objectName <- Object -> String -> Parser (Maybe Str)
forall value.
FromJSON value =>
Object -> String -> Parser (Maybe value)
Json.optional Object
object String
"object_name"
    ProductValue
value <- Object -> String -> Parser ProductValue
forall value. FromJSON value => Object -> String -> Parser value
Json.required Object
object String
"value"
    Product -> Parser Product
forall (f :: * -> *) a. Applicative f => a -> f a
pure Product :: Bool -> U32 -> Maybe Str -> ProductValue -> Product
Product { Bool
unknown :: Bool
unknown :: Bool
unknown, U32
objectId :: U32
objectId :: U32
objectId, Maybe Str
objectName :: Maybe Str
objectName :: Maybe Str
objectName, ProductValue
value :: ProductValue
value :: ProductValue
value }

instance Json.ToJSON Product where
  toJSON :: Product -> Value
toJSON Product
x = [Pair] -> Value
Json.object
    [ String -> Bool -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"unknown" (Bool -> Pair) -> Bool -> Pair
forall a b. (a -> b) -> a -> b
$ Product -> Bool
unknown Product
x
    , String -> U32 -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"object_id" (U32 -> Pair) -> U32 -> Pair
forall a b. (a -> b) -> a -> b
$ Product -> U32
objectId Product
x
    , String -> Maybe Str -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"object_name" (Maybe Str -> Pair) -> Maybe Str -> Pair
forall a b. (a -> b) -> a -> b
$ Product -> Maybe Str
objectName Product
x
    , String -> ProductValue -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"value" (ProductValue -> Pair) -> ProductValue -> Pair
forall a b. (a -> b) -> a -> b
$ Product -> ProductValue
value Product
x
    ]

schema :: Schema.Schema
schema :: Schema
schema = String -> Value -> Schema
Schema.named String
"attribute-product" (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
"unknown" (Value -> Pair) -> Value -> Pair
forall a b. (a -> b) -> a -> b
$ Schema -> Value
Schema.ref Schema
Schema.boolean, Bool
True)
  , (String -> Value -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"object_id" (Value -> Pair) -> Value -> Pair
forall a b. (a -> b) -> a -> b
$ Schema -> Value
Schema.ref Schema
U32.schema, Bool
True)
  , (String -> Value -> Pair
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"object_name" (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
Schema.maybe Schema
Str.schema, Bool
False)
  , (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
ProductValue.schema, Bool
True)
  ]

putProductAttributes :: List.List Product -> BitPut.BitPut
putProductAttributes :: List Product -> BitPut
putProductAttributes List Product
attributes =
  let v :: [Product]
v = List Product -> [Product]
forall a. List a -> [a]
List.toList List Product
attributes
  in (U8 -> BitPut
U8.bitPut (U8 -> BitPut) -> (Int -> U8) -> Int -> BitPut
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> U8
U8.fromWord8 (Word8 -> U8) -> (Int -> Word8) -> Int -> U8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> BitPut) -> Int -> BitPut
forall a b. (a -> b) -> a -> b
$ [Product] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Product]
v) BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> (Product -> BitPut) -> [Product] -> BitPut
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Product -> BitPut
bitPut [Product]
v

bitPut :: Product -> BitPut.BitPut
bitPut :: Product -> BitPut
bitPut Product
attribute =
  Bool -> BitPut
BitPut.bool (Product -> Bool
unknown Product
attribute)
    BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> U32 -> BitPut
U32.bitPut (Product -> U32
objectId Product
attribute)
    BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> ProductValue -> BitPut
ProductValue.bitPut (Product -> ProductValue
value Product
attribute)

decodeProductAttributesBits
  :: Version.Version
  -> Map.Map U32.U32 Str.Str
  -> BitGet.BitGet (List.List Product)
decodeProductAttributesBits :: Version -> Map U32 Str -> BitGet (List Product)
decodeProductAttributesBits Version
version Map U32 Str
objectMap = do
  U8
size <- BitGet U8
U8.bitGet
  Int -> Get BitString Identity Product -> BitGet (List Product)
forall (m :: * -> *) a. Monad m => Int -> m a -> m (List a)
List.replicateM (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int) -> Word8 -> Int
forall a b. (a -> b) -> a -> b
$ U8 -> Word8
U8.toWord8 U8
size) (Get BitString Identity Product -> BitGet (List Product))
-> Get BitString Identity Product -> BitGet (List Product)
forall a b. (a -> b) -> a -> b
$ Version -> Map U32 Str -> Get BitString Identity Product
bitGet Version
version Map U32 Str
objectMap

bitGet :: Version.Version -> Map.Map U32.U32 Str.Str -> BitGet.BitGet Product
bitGet :: Version -> Map U32 Str -> Get BitString Identity Product
bitGet Version
version Map U32 Str
objectMap = String
-> Get BitString Identity Product -> Get BitString Identity Product
forall a. String -> BitGet a -> BitGet a
BitGet.label String
"Product" (Get BitString Identity Product -> Get BitString Identity Product)
-> Get BitString Identity Product -> Get BitString Identity Product
forall a b. (a -> b) -> a -> b
$ do
  Bool
unknown <- String -> BitGet Bool -> BitGet Bool
forall a. String -> BitGet a -> BitGet a
BitGet.label String
"unknown" BitGet Bool
BitGet.bool
  U32
objectId <- String -> BitGet U32 -> BitGet U32
forall a. String -> BitGet a -> BitGet a
BitGet.label String
"objectId" BitGet U32
U32.bitGet
  let objectName :: Maybe Str
objectName = U32 -> Map U32 Str -> Maybe Str
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup U32
objectId Map U32 Str
objectMap
  ProductValue
value <- String -> BitGet ProductValue -> BitGet ProductValue
forall a. String -> BitGet a -> BitGet a
BitGet.label String
"value"
    (BitGet ProductValue -> BitGet ProductValue)
-> BitGet ProductValue -> BitGet ProductValue
forall a b. (a -> b) -> a -> b
$ Version -> U32 -> Maybe Str -> BitGet ProductValue
ProductValue.bitGet Version
version U32
objectId Maybe Str
objectName
  Product -> Get BitString Identity Product
forall (f :: * -> *) a. Applicative f => a -> f a
pure Product :: Bool -> U32 -> Maybe Str -> ProductValue -> Product
Product { Bool
unknown :: Bool
unknown :: Bool
unknown, U32
objectId :: U32
objectId :: U32
objectId, Maybe Str
objectName :: Maybe Str
objectName :: Maybe Str
objectName, ProductValue
value :: ProductValue
value :: ProductValue
value }