module Rattletrap.Type.Attribute.Product where

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

import qualified Data.Map as Map

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 -> BitGet 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) (BitGet Product -> BitGet (List Product))
-> BitGet Product -> BitGet (List Product)
forall a b. (a -> b) -> a -> b
$ Version -> Map U32 Str -> BitGet 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 -> BitGet Product
bitGet Version
version Map U32 Str
objectMap = do
  Bool
flag <- BitGet Bool
BitGet.bool
  U32
objectId_ <- BitGet U32
U32.bitGet
  let maybeObjectName :: Maybe Str
maybeObjectName = 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_ <- Version -> U32 -> Maybe Str -> BitGet ProductValue
ProductValue.bitGet Version
version U32
objectId_ Maybe Str
maybeObjectName
  Product -> BitGet Product
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> U32 -> Maybe Str -> ProductValue -> Product
Product Bool
flag U32
objectId_ Maybe Str
maybeObjectName ProductValue
value_)