{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE UndecidableInstances  #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module TestMarket
    ( TestMarket
    , module X
    ) where

import           Control.Applicative
import           Control.Monad
import           Data.ByteString.UTF8       as UTF8
import           Data.Csv
import           Data.Fixed                 as X
import           Finance.Exchange.OrderBook as X
import           Finance.Exchange.Portfolio as X
import           Finance.Exchange.Types     as X
import           Test.QuickCheck


type instance MarketMonad TestMarket = IO -- возможно стоит заменить на трансформер тестового фреймворка
type instance Money TestMarket = Centi
type instance InstrumentId TestMarket = TestInstrument
type instance OrderId TestMarket = Integer
type instance Amount TestMarket = Integer

data TestMarket

data TestInstrument = ICE_Brent deriving ( Show, Read, Eq, Ord )

instance ToField TestInstrument where
    toField = UTF8.fromString . show

instance FromField TestInstrument where
    parseField s = case reads $ UTF8.toString s of
        [(instrument, "")] -> pure instrument
        _                  -> mzero

instance ToField Centi where
    toField = UTF8.fromString . show

instance FromField Centi where
    parseField s = case reads $ UTF8.toString s of
        [(instrument, "")] -> pure instrument
        _                  -> mzero

instance Arbitrary TestInstrument where
    arbitrary = elements [ ICE_Brent ]

instance Arbitrary BuyOrSell where
    arbitrary = elements [ Buy, Sell ]

instance Arbitrary (OrderPrice TestMarket) where
    arbitrary = frequency [ ( 1, return Market)
                          , (10, fmap Limit arbitrary)
                          ]
    shrink Market      = []
    shrink (Limit lim) = fmap Limit $ shrink lim
{-
instance Arbitrary (Candle TestMarket) where
    arbitrary = Candle <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
-}
instance Arbitrary (PortfolioRep TestMarket) where
    arbitrary = PortfolioRep <$> arbitrary <*> fmap (fmap $ \(inst, NonZero amount) ->  (inst, amount)) arbitrary

instance Arbitrary (Portfolio TestMarket) where
    arbitrary = fromPortfolioRep <$> arbitrary
