{-# LANGUAGE FlexibleContexts, UndecidableInstances #-}
-- |Type and request for order book for all markets.
module Cryptsy.API.Public.OrderData
	( GOrderData(..), OrderData
	, parseOrderData, orderData
	, module Cryptsy.API.Public.Types.OrderBook
	, module Cryptsy.API.Public.Types.Monad
	, module Cryptsy.API.Public.Types.Num
	)
where

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

-- base
import Data.Function (($))
import Data.Functor (fmap, (<$>))
import Data.String (String)
import Data.Traversable (mapM)
import Prelude ()
import Text.Show (Show)

-- text
import Data.Text (Text)

-- unordered-containers
import Data.HashMap.Strict (HashMap)

-- this package
import Cryptsy.API.Public.Internal
import Cryptsy.API.Public.Types.OrderBook
import Cryptsy.API.Public.Types.Monad
import Cryptsy.API.Public.Types.Num

-- |general order data parameterized by types for prices, quantities,
-- and totals (price * quantity)
newtype GOrderData p q t =
	OrderData { orderBooks :: HashMap Text (GOrderBook p q t) }
	deriving Show

-- |default order data
type OrderData = GOrderData CryptsyNum CryptsyNum CryptsyNum

instance FromJSON (GOrderBook p q t) => FromJSON (GOrderData p q t) where
	parseJSON = parseOrderData parseJSON

-- |Build parser for multiple orderbooks from parser for single orderbook.
parseOrderData :: (Value -> Parser (GOrderBook p q t)) -- ^ orderbook parser
               -> Value -> Parser (GOrderData p q t)
parseOrderData parseBook =
	withObject "OrderData" $ fmap OrderData <$> mapM parseBook
{-# INLINABLE parseOrderData #-}

-- |URL for API call
orderdataURL :: String
orderdataURL = pubURL "orderdata"

-- |Request full order book for all markets.
orderData :: FromJSON (GOrderData p q t) => PubCryptsy (GOrderData p q t)
orderData = pubCryptsy orderdataURL parseJSON
{-# INLINABLE orderData #-}