{-# LANGUAGE OverloadedStrings #-}

module CoinbasePro.WebSocketFeed.Channel.Level2
    ( Snapshot (..)
    , SnapshotLevel (..)
    , Change (..)
    , L2Update(..)
    ) where

import           Data.Aeson  (FromJSON (..), withArray, withObject, (.:))
import           Data.Text   (Text)
import qualified Data.Vector as V


data SnapshotLevel = SnapshotLevel
    { SnapshotLevel -> Double
price :: Double
    , SnapshotLevel -> Double
size  :: Double
    } deriving (SnapshotLevel -> SnapshotLevel -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SnapshotLevel -> SnapshotLevel -> Bool
$c/= :: SnapshotLevel -> SnapshotLevel -> Bool
== :: SnapshotLevel -> SnapshotLevel -> Bool
$c== :: SnapshotLevel -> SnapshotLevel -> Bool
Eq, Eq SnapshotLevel
SnapshotLevel -> SnapshotLevel -> Bool
SnapshotLevel -> SnapshotLevel -> Ordering
SnapshotLevel -> SnapshotLevel -> SnapshotLevel
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SnapshotLevel -> SnapshotLevel -> SnapshotLevel
$cmin :: SnapshotLevel -> SnapshotLevel -> SnapshotLevel
max :: SnapshotLevel -> SnapshotLevel -> SnapshotLevel
$cmax :: SnapshotLevel -> SnapshotLevel -> SnapshotLevel
>= :: SnapshotLevel -> SnapshotLevel -> Bool
$c>= :: SnapshotLevel -> SnapshotLevel -> Bool
> :: SnapshotLevel -> SnapshotLevel -> Bool
$c> :: SnapshotLevel -> SnapshotLevel -> Bool
<= :: SnapshotLevel -> SnapshotLevel -> Bool
$c<= :: SnapshotLevel -> SnapshotLevel -> Bool
< :: SnapshotLevel -> SnapshotLevel -> Bool
$c< :: SnapshotLevel -> SnapshotLevel -> Bool
compare :: SnapshotLevel -> SnapshotLevel -> Ordering
$ccompare :: SnapshotLevel -> SnapshotLevel -> Ordering
Ord, Int -> SnapshotLevel -> ShowS
[SnapshotLevel] -> ShowS
SnapshotLevel -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SnapshotLevel] -> ShowS
$cshowList :: [SnapshotLevel] -> ShowS
show :: SnapshotLevel -> String
$cshow :: SnapshotLevel -> String
showsPrec :: Int -> SnapshotLevel -> ShowS
$cshowsPrec :: Int -> SnapshotLevel -> ShowS
Show)


instance FromJSON SnapshotLevel where
    parseJSON :: Value -> Parser SnapshotLevel
parseJSON = forall a. String -> (Array -> Parser a) -> Value -> Parser a
withArray String
"snapshot level" forall a b. (a -> b) -> a -> b
$ \Array
a -> do
        let l :: [Value]
l = forall a. Vector a -> [a]
V.toList Array
a
        String
p  <- forall a. FromJSON a => Value -> Parser a
parseJSON forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head [Value]
l
        String
sz <- forall a. FromJSON a => Value -> Parser a
parseJSON forall a b. (a -> b) -> a -> b
$ [Value]
l forall a. [a] -> Int -> a
!! Int
1
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Double -> Double -> SnapshotLevel
SnapshotLevel (forall a. Read a => String -> a
read String
p) (forall a. Read a => String -> a
read String
sz)


data Snapshot = Snapshot
    { Snapshot -> Text
sProductId :: Text
    , Snapshot -> [SnapshotLevel]
bids       :: [SnapshotLevel]
    , Snapshot -> [SnapshotLevel]
asks       :: [SnapshotLevel]
    } deriving (Snapshot -> Snapshot -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Snapshot -> Snapshot -> Bool
$c/= :: Snapshot -> Snapshot -> Bool
== :: Snapshot -> Snapshot -> Bool
$c== :: Snapshot -> Snapshot -> Bool
Eq, Eq Snapshot
Snapshot -> Snapshot -> Bool
Snapshot -> Snapshot -> Ordering
Snapshot -> Snapshot -> Snapshot
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Snapshot -> Snapshot -> Snapshot
$cmin :: Snapshot -> Snapshot -> Snapshot
max :: Snapshot -> Snapshot -> Snapshot
$cmax :: Snapshot -> Snapshot -> Snapshot
>= :: Snapshot -> Snapshot -> Bool
$c>= :: Snapshot -> Snapshot -> Bool
> :: Snapshot -> Snapshot -> Bool
$c> :: Snapshot -> Snapshot -> Bool
<= :: Snapshot -> Snapshot -> Bool
$c<= :: Snapshot -> Snapshot -> Bool
< :: Snapshot -> Snapshot -> Bool
$c< :: Snapshot -> Snapshot -> Bool
compare :: Snapshot -> Snapshot -> Ordering
$ccompare :: Snapshot -> Snapshot -> Ordering
Ord, Int -> Snapshot -> ShowS
[Snapshot] -> ShowS
Snapshot -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Snapshot] -> ShowS
$cshowList :: [Snapshot] -> ShowS
show :: Snapshot -> String
$cshow :: Snapshot -> String
showsPrec :: Int -> Snapshot -> ShowS
$cshowsPrec :: Int -> Snapshot -> ShowS
Show)


instance FromJSON Snapshot where
    parseJSON :: Value -> Parser Snapshot
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"snapshot" forall a b. (a -> b) -> a -> b
$ \Object
o ->
      Text -> [SnapshotLevel] -> [SnapshotLevel] -> Snapshot
Snapshot forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
        Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"product_id" forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
        Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"bids" forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
        Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"asks"


data Change = Change
    { Change -> Text
side   :: Text
    , Change -> Double
cPrice :: Double
    , Change -> Double
cSize  :: Double
    } deriving (Change -> Change -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Change -> Change -> Bool
$c/= :: Change -> Change -> Bool
== :: Change -> Change -> Bool
$c== :: Change -> Change -> Bool
Eq, Eq Change
Change -> Change -> Bool
Change -> Change -> Ordering
Change -> Change -> Change
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Change -> Change -> Change
$cmin :: Change -> Change -> Change
max :: Change -> Change -> Change
$cmax :: Change -> Change -> Change
>= :: Change -> Change -> Bool
$c>= :: Change -> Change -> Bool
> :: Change -> Change -> Bool
$c> :: Change -> Change -> Bool
<= :: Change -> Change -> Bool
$c<= :: Change -> Change -> Bool
< :: Change -> Change -> Bool
$c< :: Change -> Change -> Bool
compare :: Change -> Change -> Ordering
$ccompare :: Change -> Change -> Ordering
Ord, Int -> Change -> ShowS
[Change] -> ShowS
Change -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Change] -> ShowS
$cshowList :: [Change] -> ShowS
show :: Change -> String
$cshow :: Change -> String
showsPrec :: Int -> Change -> ShowS
$cshowsPrec :: Int -> Change -> ShowS
Show)


instance FromJSON Change where
    parseJSON :: Value -> Parser Change
parseJSON = forall a. String -> (Array -> Parser a) -> Value -> Parser a
withArray String
"change" forall a b. (a -> b) -> a -> b
$ \Array
a -> do
        let l :: [Value]
l = forall a. Vector a -> [a]
V.toList Array
a
        Text
sd <- forall a. FromJSON a => Value -> Parser a
parseJSON forall a b. (a -> b) -> a -> b
$ forall a. [a] -> a
head [Value]
l
        String
p  <- forall a. FromJSON a => Value -> Parser a
parseJSON forall a b. (a -> b) -> a -> b
$ [Value]
l forall a. [a] -> Int -> a
!! Int
1
        String
sz <- forall a. FromJSON a => Value -> Parser a
parseJSON forall a b. (a -> b) -> a -> b
$ [Value]
l forall a. [a] -> Int -> a
!! Int
2
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text -> Double -> Double -> Change
Change Text
sd (forall a. Read a => String -> a
read String
p) (forall a. Read a => String -> a
read String
sz)


data L2Update = L2Update
    { L2Update -> Text
l2ProductId :: Text
    , L2Update -> [Change]
changes     :: [Change]
    } deriving (L2Update -> L2Update -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: L2Update -> L2Update -> Bool
$c/= :: L2Update -> L2Update -> Bool
== :: L2Update -> L2Update -> Bool
$c== :: L2Update -> L2Update -> Bool
Eq, Eq L2Update
L2Update -> L2Update -> Bool
L2Update -> L2Update -> Ordering
L2Update -> L2Update -> L2Update
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: L2Update -> L2Update -> L2Update
$cmin :: L2Update -> L2Update -> L2Update
max :: L2Update -> L2Update -> L2Update
$cmax :: L2Update -> L2Update -> L2Update
>= :: L2Update -> L2Update -> Bool
$c>= :: L2Update -> L2Update -> Bool
> :: L2Update -> L2Update -> Bool
$c> :: L2Update -> L2Update -> Bool
<= :: L2Update -> L2Update -> Bool
$c<= :: L2Update -> L2Update -> Bool
< :: L2Update -> L2Update -> Bool
$c< :: L2Update -> L2Update -> Bool
compare :: L2Update -> L2Update -> Ordering
$ccompare :: L2Update -> L2Update -> Ordering
Ord, Int -> L2Update -> ShowS
[L2Update] -> ShowS
L2Update -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [L2Update] -> ShowS
$cshowList :: [L2Update] -> ShowS
show :: L2Update -> String
$cshow :: L2Update -> String
showsPrec :: Int -> L2Update -> ShowS
$cshowsPrec :: Int -> L2Update -> ShowS
Show)


instance FromJSON L2Update where
    parseJSON :: Value -> Parser L2Update
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"l2update" forall a b. (a -> b) -> a -> b
$ \Object
o ->
      Text -> [Change] -> L2Update
L2Update forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
        Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"product_id" forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
        Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"changes"