{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE OverloadedStrings #-}

module CoinbasePro.Authenticated.Fills
    ( Fill (..)
    , TradeId
    , Liquidity (..)
    ) where

import           Data.Aeson        (FromJSON (..), withObject, withText, (.:))

import           CoinbasePro.Types (CreatedAt (..), OrderId, Price, ProductId,
                                    Side, Size, TradeId (..))


data Liquidity = Maker | Taker
    deriving (Liquidity -> Liquidity -> Bool
(Liquidity -> Liquidity -> Bool)
-> (Liquidity -> Liquidity -> Bool) -> Eq Liquidity
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Liquidity -> Liquidity -> Bool
$c/= :: Liquidity -> Liquidity -> Bool
== :: Liquidity -> Liquidity -> Bool
$c== :: Liquidity -> Liquidity -> Bool
Eq, Int -> Liquidity -> ShowS
[Liquidity] -> ShowS
Liquidity -> String
(Int -> Liquidity -> ShowS)
-> (Liquidity -> String)
-> ([Liquidity] -> ShowS)
-> Show Liquidity
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Liquidity] -> ShowS
$cshowList :: [Liquidity] -> ShowS
show :: Liquidity -> String
$cshow :: Liquidity -> String
showsPrec :: Int -> Liquidity -> ShowS
$cshowsPrec :: Int -> Liquidity -> ShowS
Show)


instance FromJSON Liquidity where
    parseJSON :: Value -> Parser Liquidity
parseJSON = String -> (Text -> Parser Liquidity) -> Value -> Parser Liquidity
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"liquidity" ((Text -> Parser Liquidity) -> Value -> Parser Liquidity)
-> (Text -> Parser Liquidity) -> Value -> Parser Liquidity
forall a b. (a -> b) -> a -> b
$
      \case
        Text
"M" -> Liquidity -> Parser Liquidity
forall (m :: * -> *) a. Monad m => a -> m a
return Liquidity
Maker
        Text
"T" -> Liquidity -> Parser Liquidity
forall (m :: * -> *) a. Monad m => a -> m a
return Liquidity
Taker
        Text
_   -> String -> Parser Liquidity
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"parse error"


data Fill = Fill
    { Fill -> TradeId
tradeId   :: TradeId
    , Fill -> ProductId
productId :: ProductId
    , Fill -> Side
side      :: Side
    , Fill -> Price
price     :: Price
    , Fill -> Size
size      :: Size
    , Fill -> OrderId
orderId   :: OrderId
    , Fill -> CreatedAt
createdAt :: CreatedAt
    , Fill -> Liquidity
liquidity :: Liquidity
    , Fill -> Double
fee       :: Double
    , Fill -> Bool
settled   :: Bool
    } deriving (Fill -> Fill -> Bool
(Fill -> Fill -> Bool) -> (Fill -> Fill -> Bool) -> Eq Fill
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Fill -> Fill -> Bool
$c/= :: Fill -> Fill -> Bool
== :: Fill -> Fill -> Bool
$c== :: Fill -> Fill -> Bool
Eq, Int -> Fill -> ShowS
[Fill] -> ShowS
Fill -> String
(Int -> Fill -> ShowS)
-> (Fill -> String) -> ([Fill] -> ShowS) -> Show Fill
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Fill] -> ShowS
$cshowList :: [Fill] -> ShowS
show :: Fill -> String
$cshow :: Fill -> String
showsPrec :: Int -> Fill -> ShowS
$cshowsPrec :: Int -> Fill -> ShowS
Show)


instance FromJSON Fill where
    parseJSON :: Value -> Parser Fill
parseJSON = String -> (Object -> Parser Fill) -> Value -> Parser Fill
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"fill" ((Object -> Parser Fill) -> Value -> Parser Fill)
-> (Object -> Parser Fill) -> Value -> Parser Fill
forall a b. (a -> b) -> a -> b
$ \Object
o -> TradeId
-> ProductId
-> Side
-> Price
-> Size
-> OrderId
-> CreatedAt
-> Liquidity
-> Double
-> Bool
-> Fill
Fill
        (TradeId
 -> ProductId
 -> Side
 -> Price
 -> Size
 -> OrderId
 -> CreatedAt
 -> Liquidity
 -> Double
 -> Bool
 -> Fill)
-> Parser TradeId
-> Parser
     (ProductId
      -> Side
      -> Price
      -> Size
      -> OrderId
      -> CreatedAt
      -> Liquidity
      -> Double
      -> Bool
      -> Fill)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> TradeId
TradeId (Int -> TradeId) -> Parser Int -> Parser TradeId
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
"trade_id")
        Parser
  (ProductId
   -> Side
   -> Price
   -> Size
   -> OrderId
   -> CreatedAt
   -> Liquidity
   -> Double
   -> Bool
   -> Fill)
-> Parser ProductId
-> Parser
     (Side
      -> Price
      -> Size
      -> OrderId
      -> CreatedAt
      -> Liquidity
      -> Double
      -> Bool
      -> Fill)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser ProductId
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"product_id"
        Parser
  (Side
   -> Price
   -> Size
   -> OrderId
   -> CreatedAt
   -> Liquidity
   -> Double
   -> Bool
   -> Fill)
-> Parser Side
-> Parser
     (Price
      -> Size
      -> OrderId
      -> CreatedAt
      -> Liquidity
      -> Double
      -> Bool
      -> Fill)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Side
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"side"
        Parser
  (Price
   -> Size
   -> OrderId
   -> CreatedAt
   -> Liquidity
   -> Double
   -> Bool
   -> Fill)
-> Parser Price
-> Parser
     (Size
      -> OrderId -> CreatedAt -> Liquidity -> Double -> Bool -> Fill)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Price
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"price"
        Parser
  (Size
   -> OrderId -> CreatedAt -> Liquidity -> Double -> Bool -> Fill)
-> Parser Size
-> Parser
     (OrderId -> CreatedAt -> Liquidity -> Double -> Bool -> Fill)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Size
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"size"
        Parser
  (OrderId -> CreatedAt -> Liquidity -> Double -> Bool -> Fill)
-> Parser OrderId
-> Parser (CreatedAt -> Liquidity -> Double -> Bool -> Fill)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser OrderId
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"order_id"
        Parser (CreatedAt -> Liquidity -> Double -> Bool -> Fill)
-> Parser CreatedAt -> Parser (Liquidity -> Double -> Bool -> Fill)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (UTCTime -> CreatedAt
CreatedAt (UTCTime -> CreatedAt) -> Parser UTCTime -> Parser CreatedAt
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser UTCTime
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"created_at")
        Parser (Liquidity -> Double -> Bool -> Fill)
-> Parser Liquidity -> Parser (Double -> Bool -> Fill)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Object
o Object -> Text -> Parser Liquidity
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"liquidity")
        Parser (Double -> Bool -> Fill)
-> Parser Double -> Parser (Bool -> Fill)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (String -> Double
forall a. Read a => String -> a
read (String -> Double) -> Parser String -> Parser Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser String
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"fee")
        Parser (Bool -> Fill) -> Parser Bool -> Parser Fill
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser Bool
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"settled"