-- | This module defines 'Cooked.Tweak.Common.Tweak's revolving around the
-- signatories of a transaction. They assume but do not ensure that the list of
-- signatories is free of duplicates.
module Cooked.Tweak.Signatories
  ( getSignatoriesTweak,
    modifySignatoriesTweak,
    setSignatoriesTweak,
    signatoriesSatisfyTweak,
    isSignatoryTweak,
    hasSignatoriesTweak,
    addFirstSignatoryTweak,
    addSignatoriesTweak,
    addLastSignatoryTweak,
    removeSignatoriesTweak,
    removeSignatoryTweak,
    replaceFirstSignatoryTweak,
  )
where

import Cooked.Skeleton (TxSkelSignatory, txSkelSignatoriesL)
import Cooked.Tweak.Common (MonadTweak, setTweak, viewTweak)
import Data.List (delete, (\\))

-- | Returns the current list of signatories
getSignatoriesTweak :: (MonadTweak m) => m [TxSkelSignatory]
getSignatoriesTweak :: forall (m :: * -> *). MonadTweak m => m [TxSkelSignatory]
getSignatoriesTweak = Optic' A_Lens NoIx TxSkel [TxSkelSignatory] -> m [TxSkelSignatory]
forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Getter) =>
Optic' k is TxSkel a -> m a
viewTweak Optic' A_Lens NoIx TxSkel [TxSkelSignatory]
txSkelSignatoriesL

-- | Apply a function to the list of signatories and return the old ones
modifySignatoriesTweak :: (MonadTweak m) => ([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
modifySignatoriesTweak :: forall (m :: * -> *).
MonadTweak m =>
([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
modifySignatoriesTweak [TxSkelSignatory] -> [TxSkelSignatory]
f = do
  [TxSkelSignatory]
oldSignatories <- m [TxSkelSignatory]
forall (m :: * -> *). MonadTweak m => m [TxSkelSignatory]
getSignatoriesTweak
  Optic' A_Lens NoIx TxSkel [TxSkelSignatory]
-> [TxSkelSignatory] -> 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 [TxSkelSignatory]
txSkelSignatoriesL ([TxSkelSignatory] -> [TxSkelSignatory]
f [TxSkelSignatory]
oldSignatories)
  [TxSkelSignatory] -> m [TxSkelSignatory]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return [TxSkelSignatory]
oldSignatories

-- | Change the current signatories and return the old ones
setSignatoriesTweak :: (MonadTweak m) => [TxSkelSignatory] -> m [TxSkelSignatory]
setSignatoriesTweak :: forall (m :: * -> *).
MonadTweak m =>
[TxSkelSignatory] -> m [TxSkelSignatory]
setSignatoriesTweak = ([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
forall (m :: * -> *).
MonadTweak m =>
([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
modifySignatoriesTweak (([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory])
-> ([TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory])
-> [TxSkelSignatory]
-> m [TxSkelSignatory]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory]
forall a b. a -> b -> a
const

-- | Check if the signatories satisfy a certain predicate
signatoriesSatisfyTweak :: (MonadTweak m) => ([TxSkelSignatory] -> Bool) -> m Bool
signatoriesSatisfyTweak :: forall (m :: * -> *).
MonadTweak m =>
([TxSkelSignatory] -> Bool) -> m Bool
signatoriesSatisfyTweak = (([TxSkelSignatory] -> Bool) -> m [TxSkelSignatory] -> m Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m [TxSkelSignatory]
forall (m :: * -> *). MonadTweak m => m [TxSkelSignatory]
getSignatoriesTweak)

-- | Check if a signatory signs a transaction
isSignatoryTweak :: (MonadTweak m) => TxSkelSignatory -> m Bool
isSignatoryTweak :: forall (m :: * -> *). MonadTweak m => TxSkelSignatory -> m Bool
isSignatoryTweak = ([TxSkelSignatory] -> Bool) -> m Bool
forall (m :: * -> *).
MonadTweak m =>
([TxSkelSignatory] -> Bool) -> m Bool
signatoriesSatisfyTweak (([TxSkelSignatory] -> Bool) -> m Bool)
-> (TxSkelSignatory -> [TxSkelSignatory] -> Bool)
-> TxSkelSignatory
-> m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxSkelSignatory -> [TxSkelSignatory] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem

-- | Check if the transaction has at least a signatory
hasSignatoriesTweak :: (MonadTweak m) => m Bool
hasSignatoriesTweak :: forall (m :: * -> *). MonadTweak m => m Bool
hasSignatoriesTweak = ([TxSkelSignatory] -> Bool) -> m Bool
forall (m :: * -> *).
MonadTweak m =>
([TxSkelSignatory] -> Bool) -> m Bool
signatoriesSatisfyTweak (Bool -> Bool
not (Bool -> Bool)
-> ([TxSkelSignatory] -> Bool) -> [TxSkelSignatory] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TxSkelSignatory] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null)

-- | Add a signatory to the transaction, at the head of the list of signatories, and
-- return the old list of signatories
addFirstSignatoryTweak :: (MonadTweak m) => TxSkelSignatory -> m [TxSkelSignatory]
addFirstSignatoryTweak :: forall (m :: * -> *).
MonadTweak m =>
TxSkelSignatory -> m [TxSkelSignatory]
addFirstSignatoryTweak = ([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
forall (m :: * -> *).
MonadTweak m =>
([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
modifySignatoriesTweak (([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory])
-> (TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory])
-> TxSkelSignatory
-> m [TxSkelSignatory]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:)

-- | Add signatories at the end of the list of signatories, and return the old list of
-- signatories
addSignatoriesTweak :: (MonadTweak m) => [TxSkelSignatory] -> m [TxSkelSignatory]
addSignatoriesTweak :: forall (m :: * -> *).
MonadTweak m =>
[TxSkelSignatory] -> m [TxSkelSignatory]
addSignatoriesTweak = ([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
forall (m :: * -> *).
MonadTweak m =>
([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
modifySignatoriesTweak (([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory])
-> ([TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory])
-> [TxSkelSignatory]
-> m [TxSkelSignatory]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory]
forall a. Semigroup a => a -> a -> a
(<>)

-- | Add a signatory to the transaction, at the end of the list of signatories, and
-- return the old list of signatories
addLastSignatoryTweak :: (MonadTweak m) => TxSkelSignatory -> m [TxSkelSignatory]
addLastSignatoryTweak :: forall (m :: * -> *).
MonadTweak m =>
TxSkelSignatory -> m [TxSkelSignatory]
addLastSignatoryTweak = [TxSkelSignatory] -> m [TxSkelSignatory]
forall (m :: * -> *).
MonadTweak m =>
[TxSkelSignatory] -> m [TxSkelSignatory]
addSignatoriesTweak ([TxSkelSignatory] -> m [TxSkelSignatory])
-> (TxSkelSignatory -> [TxSkelSignatory])
-> TxSkelSignatory
-> m [TxSkelSignatory]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory]
forall a. a -> [a] -> [a]
: [])

-- | Remove signatories from the transaction and return the old list of signatories
removeSignatoriesTweak :: (MonadTweak m) => [TxSkelSignatory] -> m [TxSkelSignatory]
removeSignatoriesTweak :: forall (m :: * -> *).
MonadTweak m =>
[TxSkelSignatory] -> m [TxSkelSignatory]
removeSignatoriesTweak = ([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
forall (m :: * -> *).
MonadTweak m =>
([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
modifySignatoriesTweak (([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory])
-> ([TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory])
-> [TxSkelSignatory]
-> m [TxSkelSignatory]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory]
forall a. Eq a => [a] -> [a] -> [a]
(\\)

-- | Remove a signatory from the transaction and return the old list of signatories
removeSignatoryTweak :: (MonadTweak m) => TxSkelSignatory -> m [TxSkelSignatory]
removeSignatoryTweak :: forall (m :: * -> *).
MonadTweak m =>
TxSkelSignatory -> m [TxSkelSignatory]
removeSignatoryTweak = ([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
forall (m :: * -> *).
MonadTweak m =>
([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
modifySignatoriesTweak (([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory])
-> (TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory])
-> TxSkelSignatory
-> m [TxSkelSignatory]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory]
forall a. Eq a => a -> [a] -> [a]
delete

-- | Changes the first signatory (adds it if there are no signatories) and return the
-- old list of signatories.
replaceFirstSignatoryTweak :: (MonadTweak m) => TxSkelSignatory -> m [TxSkelSignatory]
replaceFirstSignatoryTweak :: forall (m :: * -> *).
MonadTweak m =>
TxSkelSignatory -> m [TxSkelSignatory]
replaceFirstSignatoryTweak =
  ([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
forall (m :: * -> *).
MonadTweak m =>
([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory]
modifySignatoriesTweak
    (([TxSkelSignatory] -> [TxSkelSignatory]) -> m [TxSkelSignatory])
-> (TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory])
-> TxSkelSignatory
-> m [TxSkelSignatory]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ( \TxSkelSignatory
newSignatory -> \case
          [] -> [TxSkelSignatory
newSignatory]
          (TxSkelSignatory
_ : [TxSkelSignatory]
ss) -> TxSkelSignatory
newSignatory TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory]
forall a. a -> [a] -> [a]
: [TxSkelSignatory]
ss
      )