{-# LANGUAGE OverloadedStrings #-}

module CoinbasePro.MarketData.AggregateOrderBook
    ( AggregateOrderBook(..)
    , AggregateLevel(..)
    ) where

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


data AggregateOrderBook = AggregateOrderBook
    { AggregateOrderBook -> Int
sequence :: Int
    , AggregateOrderBook -> [AggregateLevel]
bids     :: [AggregateLevel]
    , AggregateOrderBook -> [AggregateLevel]
asks     :: [AggregateLevel]
    } deriving (AggregateOrderBook -> AggregateOrderBook -> Bool
(AggregateOrderBook -> AggregateOrderBook -> Bool)
-> (AggregateOrderBook -> AggregateOrderBook -> Bool)
-> Eq AggregateOrderBook
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AggregateOrderBook -> AggregateOrderBook -> Bool
$c/= :: AggregateOrderBook -> AggregateOrderBook -> Bool
== :: AggregateOrderBook -> AggregateOrderBook -> Bool
$c== :: AggregateOrderBook -> AggregateOrderBook -> Bool
Eq, Eq AggregateOrderBook
Eq AggregateOrderBook
-> (AggregateOrderBook -> AggregateOrderBook -> Ordering)
-> (AggregateOrderBook -> AggregateOrderBook -> Bool)
-> (AggregateOrderBook -> AggregateOrderBook -> Bool)
-> (AggregateOrderBook -> AggregateOrderBook -> Bool)
-> (AggregateOrderBook -> AggregateOrderBook -> Bool)
-> (AggregateOrderBook -> AggregateOrderBook -> AggregateOrderBook)
-> (AggregateOrderBook -> AggregateOrderBook -> AggregateOrderBook)
-> Ord AggregateOrderBook
AggregateOrderBook -> AggregateOrderBook -> Bool
AggregateOrderBook -> AggregateOrderBook -> Ordering
AggregateOrderBook -> AggregateOrderBook -> AggregateOrderBook
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 :: AggregateOrderBook -> AggregateOrderBook -> AggregateOrderBook
$cmin :: AggregateOrderBook -> AggregateOrderBook -> AggregateOrderBook
max :: AggregateOrderBook -> AggregateOrderBook -> AggregateOrderBook
$cmax :: AggregateOrderBook -> AggregateOrderBook -> AggregateOrderBook
>= :: AggregateOrderBook -> AggregateOrderBook -> Bool
$c>= :: AggregateOrderBook -> AggregateOrderBook -> Bool
> :: AggregateOrderBook -> AggregateOrderBook -> Bool
$c> :: AggregateOrderBook -> AggregateOrderBook -> Bool
<= :: AggregateOrderBook -> AggregateOrderBook -> Bool
$c<= :: AggregateOrderBook -> AggregateOrderBook -> Bool
< :: AggregateOrderBook -> AggregateOrderBook -> Bool
$c< :: AggregateOrderBook -> AggregateOrderBook -> Bool
compare :: AggregateOrderBook -> AggregateOrderBook -> Ordering
$ccompare :: AggregateOrderBook -> AggregateOrderBook -> Ordering
$cp1Ord :: Eq AggregateOrderBook
Ord, Int -> AggregateOrderBook -> ShowS
[AggregateOrderBook] -> ShowS
AggregateOrderBook -> String
(Int -> AggregateOrderBook -> ShowS)
-> (AggregateOrderBook -> String)
-> ([AggregateOrderBook] -> ShowS)
-> Show AggregateOrderBook
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AggregateOrderBook] -> ShowS
$cshowList :: [AggregateOrderBook] -> ShowS
show :: AggregateOrderBook -> String
$cshow :: AggregateOrderBook -> String
showsPrec :: Int -> AggregateOrderBook -> ShowS
$cshowsPrec :: Int -> AggregateOrderBook -> ShowS
Show)


instance FromJSON AggregateOrderBook where
    parseJSON :: Value -> Parser AggregateOrderBook
parseJSON = String
-> (Object -> Parser AggregateOrderBook)
-> Value
-> Parser AggregateOrderBook
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"aggregate orderbook" ((Object -> Parser AggregateOrderBook)
 -> Value -> Parser AggregateOrderBook)
-> (Object -> Parser AggregateOrderBook)
-> Value
-> Parser AggregateOrderBook
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        Int -> [AggregateLevel] -> [AggregateLevel] -> AggregateOrderBook
AggregateOrderBook (Int -> [AggregateLevel] -> [AggregateLevel] -> AggregateOrderBook)
-> Parser Int
-> Parser
     ([AggregateLevel] -> [AggregateLevel] -> AggregateOrderBook)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
            Object
o Object -> Text -> Parser Int
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"sequence" Parser ([AggregateLevel] -> [AggregateLevel] -> AggregateOrderBook)
-> Parser [AggregateLevel]
-> Parser ([AggregateLevel] -> AggregateOrderBook)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
            Object
o Object -> Text -> Parser [AggregateLevel]
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"bids" Parser ([AggregateLevel] -> AggregateOrderBook)
-> Parser [AggregateLevel] -> Parser AggregateOrderBook
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
            Object
o Object -> Text -> Parser [AggregateLevel]
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"asks"


data AggregateLevel = AggregateLevel
    { AggregateLevel -> Double
price     :: Double
    , AggregateLevel -> Double
size      :: Double
    , AggregateLevel -> Word64
numOrders :: Word64
    } deriving (AggregateLevel -> AggregateLevel -> Bool
(AggregateLevel -> AggregateLevel -> Bool)
-> (AggregateLevel -> AggregateLevel -> Bool) -> Eq AggregateLevel
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AggregateLevel -> AggregateLevel -> Bool
$c/= :: AggregateLevel -> AggregateLevel -> Bool
== :: AggregateLevel -> AggregateLevel -> Bool
$c== :: AggregateLevel -> AggregateLevel -> Bool
Eq, Eq AggregateLevel
Eq AggregateLevel
-> (AggregateLevel -> AggregateLevel -> Ordering)
-> (AggregateLevel -> AggregateLevel -> Bool)
-> (AggregateLevel -> AggregateLevel -> Bool)
-> (AggregateLevel -> AggregateLevel -> Bool)
-> (AggregateLevel -> AggregateLevel -> Bool)
-> (AggregateLevel -> AggregateLevel -> AggregateLevel)
-> (AggregateLevel -> AggregateLevel -> AggregateLevel)
-> Ord AggregateLevel
AggregateLevel -> AggregateLevel -> Bool
AggregateLevel -> AggregateLevel -> Ordering
AggregateLevel -> AggregateLevel -> AggregateLevel
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 :: AggregateLevel -> AggregateLevel -> AggregateLevel
$cmin :: AggregateLevel -> AggregateLevel -> AggregateLevel
max :: AggregateLevel -> AggregateLevel -> AggregateLevel
$cmax :: AggregateLevel -> AggregateLevel -> AggregateLevel
>= :: AggregateLevel -> AggregateLevel -> Bool
$c>= :: AggregateLevel -> AggregateLevel -> Bool
> :: AggregateLevel -> AggregateLevel -> Bool
$c> :: AggregateLevel -> AggregateLevel -> Bool
<= :: AggregateLevel -> AggregateLevel -> Bool
$c<= :: AggregateLevel -> AggregateLevel -> Bool
< :: AggregateLevel -> AggregateLevel -> Bool
$c< :: AggregateLevel -> AggregateLevel -> Bool
compare :: AggregateLevel -> AggregateLevel -> Ordering
$ccompare :: AggregateLevel -> AggregateLevel -> Ordering
$cp1Ord :: Eq AggregateLevel
Ord, Int -> AggregateLevel -> ShowS
[AggregateLevel] -> ShowS
AggregateLevel -> String
(Int -> AggregateLevel -> ShowS)
-> (AggregateLevel -> String)
-> ([AggregateLevel] -> ShowS)
-> Show AggregateLevel
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AggregateLevel] -> ShowS
$cshowList :: [AggregateLevel] -> ShowS
show :: AggregateLevel -> String
$cshow :: AggregateLevel -> String
showsPrec :: Int -> AggregateLevel -> ShowS
$cshowsPrec :: Int -> AggregateLevel -> ShowS
Show)


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