{-# LANGUAGE OverloadedStrings #-}

module CoinbasePro.MarketData.FullOrderBook
    ( FullOrderBook (..)
    , Order (..)
    ) where

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

import           CoinbasePro.Types (OrderId (..), Price, Size)


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


instance FromJSON FullOrderBook where
    parseJSON :: Value -> Parser FullOrderBook
parseJSON = String
-> (Object -> Parser FullOrderBook)
-> Value
-> Parser FullOrderBook
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"orderbook" ((Object -> Parser FullOrderBook) -> Value -> Parser FullOrderBook)
-> (Object -> Parser FullOrderBook)
-> Value
-> Parser FullOrderBook
forall a b. (a -> b) -> a -> b
$ \Object
o ->
        Int -> [Order] -> [Order] -> FullOrderBook
FullOrderBook (Int -> [Order] -> [Order] -> FullOrderBook)
-> Parser Int -> Parser ([Order] -> [Order] -> FullOrderBook)
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 ([Order] -> [Order] -> FullOrderBook)
-> Parser [Order] -> Parser ([Order] -> FullOrderBook)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
            Object
o Object -> Text -> Parser [Order]
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"bids" Parser ([Order] -> FullOrderBook)
-> Parser [Order] -> Parser FullOrderBook
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*>
            Object
o Object -> Text -> Parser [Order]
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"asks"


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


instance FromJSON Order where
    parseJSON :: Value -> Parser Order
parseJSON = String -> (Array -> Parser Order) -> Value -> Parser Order
forall a. String -> (Array -> Parser a) -> Value -> Parser a
withArray String
"order" ((Array -> Parser Order) -> Value -> Parser Order)
-> (Array -> Parser Order) -> Value -> Parser Order
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
        Price
px  <- Value -> Parser Price
forall a. FromJSON a => Value -> Parser a
parseJSON (Value -> Parser Price) -> Value -> Parser Price
forall a b. (a -> b) -> a -> b
$ [Value] -> Value
forall a. [a] -> a
head [Value]
l
        Size
sz  <- Value -> Parser Size
forall a. FromJSON a => Value -> Parser a
parseJSON (Value -> Parser Size) -> Value -> Parser Size
forall a b. (a -> b) -> a -> b
$ [Value]
l [Value] -> Int -> Value
forall a. [a] -> Int -> a
!! Int
1
        OrderId
oid <- Value -> Parser OrderId
forall a. FromJSON a => Value -> Parser a
parseJSON (Value -> Parser OrderId) -> Value -> Parser OrderId
forall a b. (a -> b) -> a -> b
$ [Value]
l [Value] -> Int -> Value
forall a. [a] -> Int -> a
!! Int
2
        Order -> Parser Order
forall (m :: * -> *) a. Monad m => a -> m a
return (Order -> Parser Order) -> Order -> Parser Order
forall a b. (a -> b) -> a -> b
$ Price -> Size -> OrderId -> Order
Order Price
px Size
sz OrderId
oid