-- | Tweaks working on the minting part of a skeleton
module Cooked.Tweak.Mint
  ( addMintTweak,
    removeMintTweak,
  )
where

import Cooked.Skeleton
import Cooked.Tweak.Common
import Data.List (partition)
import Optics.Core
import Plutus.Script.Utils.Scripts qualified as Script
import PlutusLedgerApi.V3 qualified as Api

-- | Add a new entry to the 'TxSkelMints' of the transaction skeleton under
-- modification. As this is implemented in terms of 'addToTxSkelMints', the same
-- caveats apply as do to that function!
addMintTweak :: (MonadTweak m) => (Script.Versioned Script.MintingPolicy, TxSkelRedeemer, Api.TokenName, Integer) -> m ()
addMintTweak :: forall (m :: * -> *).
MonadTweak m =>
(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)
-> m ()
addMintTweak (Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)
mint = Optic' A_Lens NoIx TxSkel TxSkelMints
-> (TxSkelMints -> TxSkelMints) -> m ()
forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Setter) =>
Optic' k is TxSkel a -> (a -> a) -> m ()
overTweak Optic' A_Lens NoIx TxSkel TxSkelMints
txSkelMintsL ((TxSkelMints -> TxSkelMints) -> m ())
-> (TxSkelMints -> TxSkelMints) -> m ()
forall a b. (a -> b) -> a -> b
$ (Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)
-> TxSkelMints -> TxSkelMints
addToTxSkelMints (Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)
mint

-- | Remove some entries from the 'TxSkelMints' of a transaction, according to
-- some predicate. The returned list holds the removed entries.
removeMintTweak ::
  (MonadTweak m) =>
  ((Script.Versioned Script.MintingPolicy, TxSkelRedeemer, Api.TokenName, Integer) -> Bool) ->
  m [(Script.Versioned Script.MintingPolicy, TxSkelRedeemer, Api.TokenName, Integer)]
removeMintTweak :: forall (m :: * -> *).
MonadTweak m =>
((Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)
 -> Bool)
-> m [(Versioned MintingPolicy, TxSkelRedeemer, TokenName,
       Integer)]
removeMintTweak (Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)
-> Bool
removePred = do
  [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
presentMints <- Optic'
  A_Getter
  NoIx
  TxSkel
  [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
-> m [(Versioned MintingPolicy, TxSkelRedeemer, TokenName,
       Integer)]
forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Getter) =>
Optic' k is TxSkel a -> m a
viewTweak (Optic'
   A_Getter
   NoIx
   TxSkel
   [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
 -> m [(Versioned MintingPolicy, TxSkelRedeemer, TokenName,
        Integer)])
-> Optic'
     A_Getter
     NoIx
     TxSkel
     [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
-> m [(Versioned MintingPolicy, TxSkelRedeemer, TokenName,
       Integer)]
forall a b. (a -> b) -> a -> b
$ Optic' A_Lens NoIx TxSkel TxSkelMints
txSkelMintsL Optic' A_Lens NoIx TxSkel TxSkelMints
-> Optic
     A_Getter
     NoIx
     TxSkelMints
     TxSkelMints
     [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
     [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
-> Optic'
     A_Getter
     NoIx
     TxSkel
     [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% (TxSkelMints
 -> [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)])
-> Optic
     A_Getter
     NoIx
     TxSkelMints
     TxSkelMints
     [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
     [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
forall s a. (s -> a) -> Getter s a
to TxSkelMints
-> [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
txSkelMintsToList
  let ([(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
removed, [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
kept) = ((Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)
 -> Bool)
-> [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
-> ([(Versioned MintingPolicy, TxSkelRedeemer, TokenName,
      Integer)],
    [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)
-> Bool
removePred [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
presentMints
  Optic' A_Lens NoIx TxSkel TxSkelMints -> TxSkelMints -> m ()
forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Setter) =>
Optic' k is TxSkel a -> a -> m ()
setTweak Optic' A_Lens NoIx TxSkel TxSkelMints
txSkelMintsL (TxSkelMints -> m ()) -> TxSkelMints -> m ()
forall a b. (a -> b) -> a -> b
$ [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
-> TxSkelMints
txSkelMintsFromList [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
kept
  [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
-> m [(Versioned MintingPolicy, TxSkelRedeemer, TokenName,
       Integer)]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return [(Versioned MintingPolicy, TxSkelRedeemer, TokenName, Integer)]
removed