content: {-# LANGUAGE CPP #-}
  {-|
  
  
  A 'BalanceData is a data type tracking a number of postings, exclusive, and inclusive balance
  for given date ranges.
  
  -}
  module Hledger.Data.BalanceData
  ( mapBalanceData
  , opBalanceData
  
  , tests_BalanceData
  ) where
  
  
  import Test.Tasty (testGroup)
  import Test.Tasty.HUnit ((@?=), testCase)
  
  import Hledger.Data.Amount
  import Hledger.Data.Types
  
  
  instance Show BalanceData where
    showsPrec d (BalanceData e i n) =
      showParen (d > 10) $
          showString "BalanceData"
        . showString "{ bdexcludingsubs = " . showString (wbUnpack (showMixedAmountB defaultFmt e))
        . showString ", bdincludingsubs = " . showString (wbUnpack (showMixedAmountB defaultFmt i))
        . showString ", bdnumpostings = " . shows n
        . showChar '}'
  
  instance Semigroup BalanceData where
    BalanceData e i n <> BalanceData e' i' n' = BalanceData (maPlus e e') (maPlus i i') (n + n')
  
  instance Monoid BalanceData where
    mempty = BalanceData nullmixedamt nullmixedamt 0
  
  -- | Apply an operation to both 'MixedAmount' in an 'BalanceData'.
  mapBalanceData :: (MixedAmount -> MixedAmount) -> BalanceData -> BalanceData
  mapBalanceData f a = a{bdexcludingsubs = f $ bdexcludingsubs a, bdincludingsubs = f $ bdincludingsubs a}
  
  -- | Merge two 'BalanceData', using the given operation to combine their amounts.
  opBalanceData :: (MixedAmount -> MixedAmount -> MixedAmount) -> BalanceData -> BalanceData -> BalanceData
  opBalanceData f a b = a{bdexcludingsubs = f (bdexcludingsubs a) (bdexcludingsubs b), bdincludingsubs = f (bdincludingsubs a) (bdincludingsubs b)}
  
  
  -- tests
  
  tests_BalanceData = testGroup "BalanceData" [
  
    testCase "opBalanceData maPlus" $ do
      opBalanceData maPlus (BalanceData (mixed [usd 1]) (mixed [usd 2]) 5) (BalanceData (mixed [usd 3]) (mixed [usd 4]) 0)
        @?= BalanceData (mixed [usd 4]) (mixed [usd 6]) 5,
  
    testCase "opBalanceData maMinus" $ do
      opBalanceData maMinus (BalanceData (mixed [usd 1]) (mixed [usd 2]) 5) (BalanceData (mixed [usd 3]) (mixed [usd 4]) 0)
        @?= BalanceData (mixed [usd (-2)]) (mixed [usd (-2)]) 5
    ]
  