-- | This module exposes the notion of reference scripts used in our
-- 'Cooked.Skeleton.TxSkel'
module Cooked.Skeleton.ReferenceScript
  ( ReferenceScriptConstrs,
    TxSkelOutReferenceScript (..),
    txSkelOutTypedRefScriptAT,
    txSkelOutRefScriptVersioned,
    txSkelOutRefScriptHash,
  )
where

import Data.Typeable
import Optics.Core
import Plutus.Script.Utils.Scripts qualified as Script
import PlutusLedgerApi.V3 qualified as Api

-- | Type constraints over the reference script in a
-- 'Cooked.Skeleton.Ouput.TxSkelOut'
type ReferenceScriptConstrs refScript =
  ( Script.ToVersioned Script.Script refScript,
    Show refScript,
    Typeable refScript
  )

-- | Reference scripts in 'Cooked.Skeleton.Ouput.TxSkelOut'
data TxSkelOutReferenceScript where
  TxSkelOutNoReferenceScript :: TxSkelOutReferenceScript
  TxSkelOutSomeReferenceScript :: (ReferenceScriptConstrs a) => a -> TxSkelOutReferenceScript

deriving instance Show TxSkelOutReferenceScript

-- | Retrieving, or setting, a typed reference script
txSkelOutTypedRefScriptAT :: (ReferenceScriptConstrs a) => AffineTraversal' TxSkelOutReferenceScript a
txSkelOutTypedRefScriptAT :: forall a.
ReferenceScriptConstrs a =>
AffineTraversal' TxSkelOutReferenceScript a
txSkelOutTypedRefScriptAT =
  (TxSkelOutReferenceScript -> Either TxSkelOutReferenceScript a)
-> (TxSkelOutReferenceScript -> a -> TxSkelOutReferenceScript)
-> AffineTraversal
     TxSkelOutReferenceScript TxSkelOutReferenceScript a a
forall s t a b.
(s -> Either t a) -> (s -> b -> t) -> AffineTraversal s t a b
atraversal
    ( \TxSkelOutReferenceScript
x -> case TxSkelOutReferenceScript
x of
        TxSkelOutReferenceScript
TxSkelOutNoReferenceScript -> TxSkelOutReferenceScript -> Either TxSkelOutReferenceScript a
forall a b. a -> Either a b
Left TxSkelOutReferenceScript
x
        TxSkelOutSomeReferenceScript a
script -> Either TxSkelOutReferenceScript a
-> (a -> Either TxSkelOutReferenceScript a)
-> Maybe a
-> Either TxSkelOutReferenceScript a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (TxSkelOutReferenceScript -> Either TxSkelOutReferenceScript a
forall a b. a -> Either a b
Left TxSkelOutReferenceScript
x) a -> Either TxSkelOutReferenceScript a
forall a b. b -> Either a b
Right (a -> Maybe a
forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
script)
    )
    ( (a -> TxSkelOutReferenceScript -> TxSkelOutReferenceScript)
-> TxSkelOutReferenceScript -> a -> TxSkelOutReferenceScript
forall a b c. (a -> b -> c) -> b -> a -> c
flip
        ( \a
refScript -> \case
            TxSkelOutReferenceScript
TxSkelOutNoReferenceScript -> TxSkelOutReferenceScript
TxSkelOutNoReferenceScript
            TxSkelOutSomeReferenceScript a
_ -> a -> TxSkelOutReferenceScript
forall a. ReferenceScriptConstrs a => a -> TxSkelOutReferenceScript
TxSkelOutSomeReferenceScript a
refScript
        )
    )

-- | Retrieving the versioned reference script
txSkelOutRefScriptVersioned :: TxSkelOutReferenceScript -> Maybe (Script.Versioned Script.Script)
txSkelOutRefScriptVersioned :: TxSkelOutReferenceScript -> Maybe (Versioned Script)
txSkelOutRefScriptVersioned TxSkelOutReferenceScript
TxSkelOutNoReferenceScript = Maybe (Versioned Script)
forall a. Maybe a
Nothing
txSkelOutRefScriptVersioned (TxSkelOutSomeReferenceScript a
content) = Versioned Script -> Maybe (Versioned Script)
forall a. a -> Maybe a
Just (Versioned Script -> Maybe (Versioned Script))
-> Versioned Script -> Maybe (Versioned Script)
forall a b. (a -> b) -> a -> b
$ a -> Versioned Script
forall s a. ToVersioned s a => a -> Versioned s
Script.toVersioned a
content

-- | Retrieving the hash of the reference script
txSkelOutRefScriptHash :: TxSkelOutReferenceScript -> Maybe Api.ScriptHash
txSkelOutRefScriptHash :: TxSkelOutReferenceScript -> Maybe ScriptHash
txSkelOutRefScriptHash = (Versioned Script -> ScriptHash)
-> Maybe (Versioned Script) -> Maybe ScriptHash
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Versioned Script -> ScriptHash
forall a. ToScriptHash a => a -> ScriptHash
Script.toScriptHash (Maybe (Versioned Script) -> Maybe ScriptHash)
-> (TxSkelOutReferenceScript -> Maybe (Versioned Script))
-> TxSkelOutReferenceScript
-> Maybe ScriptHash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TxSkelOutReferenceScript -> Maybe (Versioned Script)
txSkelOutRefScriptVersioned