module Rattletrap.Type.RemoteId.PsyNet where

import qualified Rattletrap.BitGet as BitGet
import qualified Rattletrap.BitPut as BitPut
import qualified Rattletrap.Schema as Schema
import qualified Rattletrap.Type.U64 as U64
import qualified Rattletrap.Type.Version as Version
import qualified Rattletrap.Utility.Json as Json

newtype PsyNet
  = PsyNet (Either U64.U64 (U64.U64, U64.U64, U64.U64, U64.U64))
  deriving (PsyNet -> PsyNet -> Bool
(PsyNet -> PsyNet -> Bool)
-> (PsyNet -> PsyNet -> Bool) -> Eq PsyNet
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PsyNet -> PsyNet -> Bool
$c/= :: PsyNet -> PsyNet -> Bool
== :: PsyNet -> PsyNet -> Bool
$c== :: PsyNet -> PsyNet -> Bool
Eq, Int -> PsyNet -> ShowS
[PsyNet] -> ShowS
PsyNet -> String
(Int -> PsyNet -> ShowS)
-> (PsyNet -> String) -> ([PsyNet] -> ShowS) -> Show PsyNet
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PsyNet] -> ShowS
$cshowList :: [PsyNet] -> ShowS
show :: PsyNet -> String
$cshow :: PsyNet -> String
showsPrec :: Int -> PsyNet -> ShowS
$cshowsPrec :: Int -> PsyNet -> ShowS
Show)

instance Json.FromJSON PsyNet where
  parseJSON :: Value -> Parser PsyNet
parseJSON = (Either U64 (U64, U64, U64, U64) -> PsyNet)
-> Parser (Either U64 (U64, U64, U64, U64)) -> Parser PsyNet
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Either U64 (U64, U64, U64, U64) -> PsyNet
fromEither (Parser (Either U64 (U64, U64, U64, U64)) -> Parser PsyNet)
-> (Value -> Parser (Either U64 (U64, U64, U64, U64)))
-> Value
-> Parser PsyNet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Parser (Either U64 (U64, U64, U64, U64))
forall a. FromJSON a => Value -> Parser a
Json.parseJSON

instance Json.ToJSON PsyNet where
  toJSON :: PsyNet -> Value
toJSON = Either U64 (U64, U64, U64, U64) -> Value
forall a. ToJSON a => a -> Value
Json.toJSON (Either U64 (U64, U64, U64, U64) -> Value)
-> (PsyNet -> Either U64 (U64, U64, U64, U64)) -> PsyNet -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PsyNet -> Either U64 (U64, U64, U64, U64)
toEither

fromEither :: Either U64.U64 (U64.U64, U64.U64, U64.U64, U64.U64) -> PsyNet
fromEither :: Either U64 (U64, U64, U64, U64) -> PsyNet
fromEither = Either U64 (U64, U64, U64, U64) -> PsyNet
PsyNet

toEither :: PsyNet -> Either U64.U64 (U64.U64, U64.U64, U64.U64, U64.U64)
toEither :: PsyNet -> Either U64 (U64, U64, U64, U64)
toEither (PsyNet Either U64 (U64, U64, U64, U64)
x) = Either U64 (U64, U64, U64, U64)
x

schema :: Schema.Schema
schema :: Schema
schema = String -> Value -> Schema
Schema.named String
"remote-id-psy-net" (Value -> Schema) -> Value -> Schema
forall a b. (a -> b) -> a -> b
$ [Value] -> Value
Schema.oneOf
  [ [((Text, Value), Bool)] -> Value
Schema.object [(String -> Value -> (Text, Value)
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"Left" (Value -> (Text, Value)) -> Value -> (Text, Value)
forall a b. (a -> b) -> a -> b
$ Schema -> Value
Schema.ref Schema
U64.schema, Bool
True)]
  , [((Text, Value), Bool)] -> Value
Schema.object
    [ ( String -> Value -> (Text, Value)
forall value pair.
(ToJSON value, KeyValue pair) =>
String -> value -> pair
Json.pair String
"Right" (Value -> (Text, Value))
-> (Value -> Value) -> Value -> (Text, Value)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Value] -> Value
Schema.tuple ([Value] -> Value) -> (Value -> [Value]) -> Value -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Value -> [Value]
forall a. Int -> a -> [a]
replicate Int
4 (Value -> (Text, Value)) -> Value -> (Text, Value)
forall a b. (a -> b) -> a -> b
$ Schema -> Value
Schema.ref Schema
U64.schema
      , Bool
True
      )
    ]
  ]

bitPut :: PsyNet -> BitPut.BitPut
bitPut :: PsyNet -> BitPut
bitPut PsyNet
x = case PsyNet -> Either U64 (U64, U64, U64, U64)
toEither PsyNet
x of
  Left U64
l -> U64 -> BitPut
U64.bitPut U64
l
  Right (U64
a, U64
b, U64
c, U64
d) ->
    U64 -> BitPut
U64.bitPut U64
a BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> U64 -> BitPut
U64.bitPut U64
b BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> U64 -> BitPut
U64.bitPut U64
c BitPut -> BitPut -> BitPut
forall a. Semigroup a => a -> a -> a
<> U64 -> BitPut
U64.bitPut U64
d

bitGet :: Version.Version -> BitGet.BitGet PsyNet
bitGet :: Version -> BitGet PsyNet
bitGet Version
version = (Either U64 (U64, U64, U64, U64) -> PsyNet)
-> Get BitString Identity (Either U64 (U64, U64, U64, U64))
-> BitGet PsyNet
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Either U64 (U64, U64, U64, U64) -> PsyNet
fromEither (Get BitString Identity (Either U64 (U64, U64, U64, U64))
 -> BitGet PsyNet)
-> Get BitString Identity (Either U64 (U64, U64, U64, U64))
-> BitGet PsyNet
forall a b. (a -> b) -> a -> b
$ if Int -> Int -> Int -> Version -> Bool
Version.atLeast Int
868 Int
24 Int
10 Version
version
  then (U64 -> Either U64 (U64, U64, U64, U64))
-> Get BitString Identity U64
-> Get BitString Identity (Either U64 (U64, U64, U64, U64))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap U64 -> Either U64 (U64, U64, U64, U64)
forall a b. a -> Either a b
Left Get BitString Identity U64
U64.bitGet
  else ((U64, U64, U64, U64) -> Either U64 (U64, U64, U64, U64))
-> Get BitString Identity (U64, U64, U64, U64)
-> Get BitString Identity (Either U64 (U64, U64, U64, U64))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (U64, U64, U64, U64) -> Either U64 (U64, U64, U64, U64)
forall a b. b -> Either a b
Right (Get BitString Identity (U64, U64, U64, U64)
 -> Get BitString Identity (Either U64 (U64, U64, U64, U64)))
-> Get BitString Identity (U64, U64, U64, U64)
-> Get BitString Identity (Either U64 (U64, U64, U64, U64))
forall a b. (a -> b) -> a -> b
$ do
    U64
a <- Get BitString Identity U64
U64.bitGet
    U64
b <- Get BitString Identity U64
U64.bitGet
    U64
c <- Get BitString Identity U64
U64.bitGet
    U64
d <- Get BitString Identity U64
U64.bitGet
    (U64, U64, U64, U64) -> Get BitString Identity (U64, U64, U64, U64)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (U64
a, U64
b, U64
c, U64
d)