-- |Type for individual orders (order book entries) from the API.
module Cryptsy.API.Public.Types.Order
	( module Cryptsy.API.Public.Types.Order
	, module Cryptsy.API.Public.Types.Num
	)
where

-- base
import Control.Applicative ((<$>), (<*>))

-- text
import Data.Text (pack)

-- aeson
import Data.Aeson (FromJSON(..), Value, withObject, (.:))
import Data.Aeson.Types (Parser)

-- this package
import Cryptsy.API.Public.Types.Num

-- |generalized order
data GOrder p q t = Order
	{ orderPrice :: p
	, orderQuantity :: q
	, orderTotal :: t
	} deriving Show

-- |default order
type Order = GOrder CryptsyNum CryptsyNum CryptsyNum

instance (FromJSON p, FromJSON q, FromJSON t) =>
	FromJSON (GOrder p q t)
 where
	parseJSON = parseOrder parseJSON parseJSON parseJSON

-- |Combine component parsers into JSON Object parser.
parseOrder :: (Value -> Parser p) -- ^ price parser
           -> (Value -> Parser q) -- ^ quantity parser
           -> (Value -> Parser t) -- ^ total parser
           -> Value -> Parser (GOrder p q t)
parseOrder parsePrice parseQuantity parseTotal =
	withObject "Order" $ \o -> Order         <$>
	(o .: pack "price"    >>= parsePrice   ) <*>
	(o .: pack "quantity" >>= parseQuantity) <*>
	(o .: pack "total"    >>= parseTotal   )
{-# INLINABLE parseOrder #-}