-- | 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
import Cooked.Tweak.Common
import Data.List (delete, (\\))
import Polysemy

-- | Returns the current list of signatories
getSignatoriesTweak ::
  (Member Tweak effs) =>
  Sem effs [TxSkelSignatory]
getSignatoriesTweak :: forall (effs :: EffectRow).
Member Tweak effs =>
Sem effs [TxSkelSignatory]
getSignatoriesTweak = Optic' A_Lens NoIx TxSkel [TxSkelSignatory]
-> Sem effs [TxSkelSignatory]
forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Getter) =>
Optic' k is TxSkel a -> Sem effs a
viewTweak Optic' A_Lens NoIx TxSkel [TxSkelSignatory]
txSkelSignatoriesL

-- | Apply a function to the list of signatories and return the old ones
modifySignatoriesTweak ::
  (Member Tweak effs) =>
  ([TxSkelSignatory] -> [TxSkelSignatory]) ->
  Sem effs [TxSkelSignatory]
modifySignatoriesTweak :: forall (effs :: EffectRow).
Member Tweak effs =>
([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
modifySignatoriesTweak [TxSkelSignatory] -> [TxSkelSignatory]
f = do
  [TxSkelSignatory]
oldSignatories <- Sem effs [TxSkelSignatory]
forall (effs :: EffectRow).
Member Tweak effs =>
Sem effs [TxSkelSignatory]
getSignatoriesTweak
  Optic' A_Lens NoIx TxSkel [TxSkelSignatory]
-> [TxSkelSignatory] -> Sem effs ()
forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Setter) =>
Optic' k is TxSkel a -> a -> Sem effs ()
setTweak Optic' A_Lens NoIx TxSkel [TxSkelSignatory]
txSkelSignatoriesL ([TxSkelSignatory] -> [TxSkelSignatory]
f [TxSkelSignatory]
oldSignatories)
  [TxSkelSignatory] -> Sem effs [TxSkelSignatory]
forall (a :: OpticKind). a -> Sem effs a
forall (m :: OpticKind -> OpticKind) (a :: OpticKind).
Monad m =>
a -> m a
return [TxSkelSignatory]
oldSignatories

-- | Change the current signatories and return the old ones
setSignatoriesTweak ::
  (Member Tweak effs) =>
  [TxSkelSignatory] ->
  Sem effs [TxSkelSignatory]
setSignatoriesTweak :: forall (effs :: EffectRow).
Member Tweak effs =>
[TxSkelSignatory] -> Sem effs [TxSkelSignatory]
setSignatoriesTweak = ([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
forall (effs :: EffectRow).
Member Tweak effs =>
([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
modifySignatoriesTweak (([TxSkelSignatory] -> [TxSkelSignatory])
 -> Sem effs [TxSkelSignatory])
-> ([TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory])
-> [TxSkelSignatory]
-> Sem effs [TxSkelSignatory]
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. [TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory]
forall (a :: OpticKind) (b :: OpticKind). a -> b -> a
const

-- | Check if the signatories satisfy a certain predicate
signatoriesSatisfyTweak ::
  (Member Tweak effs) =>
  ([TxSkelSignatory] -> Bool) ->
  Sem effs Bool
signatoriesSatisfyTweak :: forall (effs :: EffectRow).
Member Tweak effs =>
([TxSkelSignatory] -> Bool) -> Sem effs Bool
signatoriesSatisfyTweak = (([TxSkelSignatory] -> Bool)
-> Sem effs [TxSkelSignatory] -> Sem effs Bool
forall (f :: OpticKind -> OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Functor f =>
(a -> b) -> f a -> f b
<$> Sem effs [TxSkelSignatory]
forall (effs :: EffectRow).
Member Tweak effs =>
Sem effs [TxSkelSignatory]
getSignatoriesTweak)

-- | Check if a signatory signs a transaction
isSignatoryTweak ::
  (Member Tweak effs) =>
  TxSkelSignatory ->
  Sem effs Bool
isSignatoryTweak :: forall (effs :: EffectRow).
Member Tweak effs =>
TxSkelSignatory -> Sem effs Bool
isSignatoryTweak = ([TxSkelSignatory] -> Bool) -> Sem effs Bool
forall (effs :: EffectRow).
Member Tweak effs =>
([TxSkelSignatory] -> Bool) -> Sem effs Bool
signatoriesSatisfyTweak (([TxSkelSignatory] -> Bool) -> Sem effs Bool)
-> (TxSkelSignatory -> [TxSkelSignatory] -> Bool)
-> TxSkelSignatory
-> Sem effs Bool
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. TxSkelSignatory -> [TxSkelSignatory] -> Bool
forall (a :: OpticKind). Eq a => a -> [a] -> Bool
forall (t :: OpticKind -> OpticKind) (a :: OpticKind).
(Foldable t, Eq a) =>
a -> t a -> Bool
elem

-- | Check if the transaction has at least a signatory
hasSignatoriesTweak ::
  (Member Tweak effs) =>
  Sem effs Bool
hasSignatoriesTweak :: forall (effs :: EffectRow). Member Tweak effs => Sem effs Bool
hasSignatoriesTweak = ([TxSkelSignatory] -> Bool) -> Sem effs Bool
forall (effs :: EffectRow).
Member Tweak effs =>
([TxSkelSignatory] -> Bool) -> Sem effs Bool
signatoriesSatisfyTweak (Bool -> Bool
not (Bool -> Bool)
-> ([TxSkelSignatory] -> Bool) -> [TxSkelSignatory] -> Bool
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. [TxSkelSignatory] -> Bool
forall (a :: OpticKind). [a] -> Bool
forall (t :: OpticKind -> OpticKind) (a :: OpticKind).
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 ::
  (Member Tweak effs) =>
  TxSkelSignatory ->
  Sem effs [TxSkelSignatory]
addFirstSignatoryTweak :: forall (effs :: EffectRow).
Member Tweak effs =>
TxSkelSignatory -> Sem effs [TxSkelSignatory]
addFirstSignatoryTweak = ([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
forall (effs :: EffectRow).
Member Tweak effs =>
([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
modifySignatoriesTweak (([TxSkelSignatory] -> [TxSkelSignatory])
 -> Sem effs [TxSkelSignatory])
-> (TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory])
-> TxSkelSignatory
-> Sem effs [TxSkelSignatory]
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. (:)

-- | Add signatories at the end of the list of signatories, and return the old list of
-- signatories
addSignatoriesTweak ::
  (Member Tweak effs) =>
  [TxSkelSignatory] ->
  Sem effs [TxSkelSignatory]
addSignatoriesTweak :: forall (effs :: EffectRow).
Member Tweak effs =>
[TxSkelSignatory] -> Sem effs [TxSkelSignatory]
addSignatoriesTweak = ([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
forall (effs :: EffectRow).
Member Tweak effs =>
([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
modifySignatoriesTweak (([TxSkelSignatory] -> [TxSkelSignatory])
 -> Sem effs [TxSkelSignatory])
-> ([TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory])
-> [TxSkelSignatory]
-> Sem effs [TxSkelSignatory]
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. [TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory]
forall (a :: OpticKind). 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 ::
  (Member Tweak effs) =>
  TxSkelSignatory ->
  Sem effs [TxSkelSignatory]
addLastSignatoryTweak :: forall (effs :: EffectRow).
Member Tweak effs =>
TxSkelSignatory -> Sem effs [TxSkelSignatory]
addLastSignatoryTweak = [TxSkelSignatory] -> Sem effs [TxSkelSignatory]
forall (effs :: EffectRow).
Member Tweak effs =>
[TxSkelSignatory] -> Sem effs [TxSkelSignatory]
addSignatoriesTweak ([TxSkelSignatory] -> Sem effs [TxSkelSignatory])
-> (TxSkelSignatory -> [TxSkelSignatory])
-> TxSkelSignatory
-> Sem effs [TxSkelSignatory]
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. (TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory]
forall (a :: OpticKind). a -> [a] -> [a]
: [])

-- | Remove signatories from the transaction and return the old list of signatories
removeSignatoriesTweak ::
  (Member Tweak effs) =>
  [TxSkelSignatory] ->
  Sem effs [TxSkelSignatory]
removeSignatoriesTweak :: forall (effs :: EffectRow).
Member Tweak effs =>
[TxSkelSignatory] -> Sem effs [TxSkelSignatory]
removeSignatoriesTweak = ([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
forall (effs :: EffectRow).
Member Tweak effs =>
([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
modifySignatoriesTweak (([TxSkelSignatory] -> [TxSkelSignatory])
 -> Sem effs [TxSkelSignatory])
-> ([TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory])
-> [TxSkelSignatory]
-> Sem effs [TxSkelSignatory]
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. [TxSkelSignatory] -> [TxSkelSignatory] -> [TxSkelSignatory]
forall (a :: OpticKind). Eq a => [a] -> [a] -> [a]
(\\)

-- | Remove a signatory from the transaction and return the old list of signatories
removeSignatoryTweak ::
  (Member Tweak effs) =>
  TxSkelSignatory ->
  Sem effs [TxSkelSignatory]
removeSignatoryTweak :: forall (effs :: EffectRow).
Member Tweak effs =>
TxSkelSignatory -> Sem effs [TxSkelSignatory]
removeSignatoryTweak = ([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
forall (effs :: EffectRow).
Member Tweak effs =>
([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
modifySignatoriesTweak (([TxSkelSignatory] -> [TxSkelSignatory])
 -> Sem effs [TxSkelSignatory])
-> (TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory])
-> TxSkelSignatory
-> Sem effs [TxSkelSignatory]
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory]
forall (a :: OpticKind). 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 ::
  (Member Tweak effs) =>
  TxSkelSignatory ->
  Sem effs [TxSkelSignatory]
replaceFirstSignatoryTweak :: forall (effs :: EffectRow).
Member Tweak effs =>
TxSkelSignatory -> Sem effs [TxSkelSignatory]
replaceFirstSignatoryTweak =
  ([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
forall (effs :: EffectRow).
Member Tweak effs =>
([TxSkelSignatory] -> [TxSkelSignatory])
-> Sem effs [TxSkelSignatory]
modifySignatoriesTweak
    (([TxSkelSignatory] -> [TxSkelSignatory])
 -> Sem effs [TxSkelSignatory])
-> (TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory])
-> TxSkelSignatory
-> Sem effs [TxSkelSignatory]
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. ( \TxSkelSignatory
newSignatory -> \case
          [] -> [TxSkelSignatory
newSignatory]
          (TxSkelSignatory
_ : [TxSkelSignatory]
ss) -> TxSkelSignatory
newSignatory TxSkelSignatory -> [TxSkelSignatory] -> [TxSkelSignatory]
forall (a :: OpticKind). a -> [a] -> [a]
: [TxSkelSignatory]
ss
      )