{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}

-- | abstract the 'Core.Value` type family into a type class that can be
-- interacted with somewhat generically.
module Test.Cardano.Ledger.ValueFromList where

import Cardano.Ledger.Coin
import Cardano.Ledger.Mary.Value as Mary (
  AssetName,
  MaryValue (..),
  MultiAsset (..),
  PolicyID (..),
  insertMultiAsset,
  multiAssetFromList,
 )
import Cardano.Ledger.Val as Val
import Data.Map.Strict as Map

class Val.Val val => ValueFromList val where
  valueFromList :: Integer -> [(PolicyID, AssetName, Integer)] -> val

  insert :: (Integer -> Integer -> Integer) -> PolicyID -> AssetName -> Integer -> val -> val

  gettriples :: val -> (Integer, [(PolicyID, AssetName, Integer)])

instance ValueFromList MaryValue where
  valueFromList :: Integer -> [(PolicyID, AssetName, Integer)] -> MaryValue
valueFromList Integer
c [(PolicyID, AssetName, Integer)]
triples = Coin -> MultiAsset -> MaryValue
MaryValue (Integer -> Coin
Coin Integer
c) ([(PolicyID, AssetName, Integer)] -> MultiAsset
Mary.multiAssetFromList [(PolicyID, AssetName, Integer)]
triples)

  insert :: (Integer -> Integer -> Integer)
-> PolicyID -> AssetName -> Integer -> MaryValue -> MaryValue
insert Integer -> Integer -> Integer
combine PolicyID
pid AssetName
an Integer
new (MaryValue Coin
c MultiAsset
ma) = Coin -> MultiAsset -> MaryValue
MaryValue Coin
c forall a b. (a -> b) -> a -> b
$ (Integer -> Integer -> Integer)
-> PolicyID -> AssetName -> Integer -> MultiAsset -> MultiAsset
Mary.insertMultiAsset Integer -> Integer -> Integer
combine PolicyID
pid AssetName
an Integer
new MultiAsset
ma

  gettriples :: MaryValue -> (Integer, [(PolicyID, AssetName, Integer)])
gettriples (MaryValue (Coin Integer
c) (MultiAsset Map PolicyID (Map AssetName Integer)
m1)) = (Integer
c, [(PolicyID, AssetName, Integer)]
triples)
    where
      triples :: [(PolicyID, AssetName, Integer)]
triples =
        [ (PolicyID
policyId, AssetName
aname, Integer
amount)
        | (PolicyID
policyId, Map AssetName Integer
m2) <- forall k a. Map k a -> [(k, a)]
Map.toList Map PolicyID (Map AssetName Integer)
m1
        , (AssetName
aname, Integer
amount) <- forall k a. Map k a -> [(k, a)]
Map.toList Map AssetName Integer
m2
        ]