{-# LANGUAGE UndecidableInstances #-}
-- |Type for all data returned by a market data request.
module Cryptsy.API.Public.Types.MarketData
	( module Cryptsy.API.Public.Types.MarketData
	, module Cryptsy.API.Public.Types.Market
	, module Cryptsy.API.Public.Types.Num
	, module Cryptsy.API.Public.Types.Time
	)
where

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

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

-- text
import Data.Text (Text)

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

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

-- |general market data parameterized by types for prices, quantities,
-- date/time values, and totals (price * quantity)
newtype GMarketData p q dt t =
	MarketData { markets :: HashMap Text (GMarket p q dt t) }
	deriving Show

-- |default market data
type MarketData = GMarketData CryptsyNum CryptsyNum CryptsyTime CryptsyNum

instance FromJSON (GMarket p q dt t) => FromJSON (GMarketData p q dt t) where
	parseJSON = parseMarketData parseJSON

-- |Build parser for multiple markets from parser for single market.
parseMarketData :: (Value -> Parser (GMarket p q dt t)) -- ^ market parser
                -> Value -> Parser (GMarketData p q dt t)
parseMarketData parseSingle =
	withObject "MarketData" $ fmap MarketData <$> mapM parseSingle
{-# INLINABLE parseMarketData #-}