module Sqel.Data.Uid where

import qualified Data.Aeson as Aeson
import Data.Aeson (FromJSON (..), ToJSON (..), genericParseJSON, object, withObject, (.:), (.=))
import qualified Data.UUID as UUID
import Data.UUID (UUID)

data Uid i a =
  Uid {
    forall i a. Uid i a -> i
id :: i,
    forall i a. Uid i a -> a
payload :: a
  }
  deriving stock (Uid i a -> Uid i a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall i a. (Eq i, Eq a) => Uid i a -> Uid i a -> Bool
/= :: Uid i a -> Uid i a -> Bool
$c/= :: forall i a. (Eq i, Eq a) => Uid i a -> Uid i a -> Bool
== :: Uid i a -> Uid i a -> Bool
$c== :: forall i a. (Eq i, Eq a) => Uid i a -> Uid i a -> Bool
Eq, Int -> Uid i a -> ShowS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall i a. (Show i, Show a) => Int -> Uid i a -> ShowS
forall i a. (Show i, Show a) => [Uid i a] -> ShowS
forall i a. (Show i, Show a) => Uid i a -> String
showList :: [Uid i a] -> ShowS
$cshowList :: forall i a. (Show i, Show a) => [Uid i a] -> ShowS
show :: Uid i a -> String
$cshow :: forall i a. (Show i, Show a) => Uid i a -> String
showsPrec :: Int -> Uid i a -> ShowS
$cshowsPrec :: forall i a. (Show i, Show a) => Int -> Uid i a -> ShowS
Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall i a x. Rep (Uid i a) x -> Uid i a
forall i a x. Uid i a -> Rep (Uid i a) x
$cto :: forall i a x. Rep (Uid i a) x -> Uid i a
$cfrom :: forall i a x. Uid i a -> Rep (Uid i a) x
Generic, forall a b. a -> Uid i b -> Uid i a
forall a b. (a -> b) -> Uid i a -> Uid i b
forall i a b. a -> Uid i b -> Uid i a
forall i a b. (a -> b) -> Uid i a -> Uid i b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Uid i b -> Uid i a
$c<$ :: forall i a b. a -> Uid i b -> Uid i a
fmap :: forall a b. (a -> b) -> Uid i a -> Uid i b
$cfmap :: forall i a b. (a -> b) -> Uid i a -> Uid i b
Functor)

instance (FromJSON a, FromJSON i) => FromJSON (Uid i a) where
  parseJSON :: Value -> Parser (Uid i a)
parseJSON Value
v =
    forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Uid" Object -> Parser (Uid i a)
parseFlat Value
v forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
Aeson.defaultOptions Value
v
    where
      parseFlat :: Object -> Parser (Uid i a)
parseFlat Object
o =
        forall i a. i -> a -> Uid i a
Uid forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id" forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. FromJSON a => Value -> Parser a
parseJSON Value
v

instance (ToJSON a, ToJSON i) => ToJSON (Uid i a) where
  toJSON :: Uid i a -> Value
toJSON (Uid i
id' a
a) =
    [Pair] -> Value
object [Key
"id" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. ToJSON a => a -> Value
toJSON i
id', Key
"payload" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= a
a]

type Uuid =
  Uid UUID

intUUID :: Int -> UUID
intUUID :: Int -> UUID
intUUID Int
int =
  Word32 -> Word32 -> Word32 -> Word32 -> UUID
UUID.fromWords Word32
i' Word32
i' Word32
i' Word32
i'
  where
    i' :: Word32
i' =
      forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
int

intUuid :: Int -> a -> Uuid a
intUuid :: forall a. Int -> a -> Uuid a
intUuid Int
i' =
  forall i a. i -> a -> Uid i a
Uid (Int -> UUID
intUUID Int
i')