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

import Data.Function (on)
import Data.Typeable
import Optics.Core
import Plutus.Script.Utils.Scripts qualified as Script
import PlutusLedgerApi.V3 qualified as Api

-- | Reference scripts are typeable and can be converted to versioned scripts.
type ReferenceScriptConstrs refScript =
  ( Script.ToVersioned Script.Script refScript,
    Typeable refScript
  )

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

instance Eq TxSkelOutReferenceScript where
  == :: TxSkelOutReferenceScript -> TxSkelOutReferenceScript -> Bool
(==) = Maybe ScriptHash -> Maybe ScriptHash -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Maybe ScriptHash -> Maybe ScriptHash -> Bool)
-> (TxSkelOutReferenceScript -> Maybe ScriptHash)
-> TxSkelOutReferenceScript
-> TxSkelOutReferenceScript
-> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Optic' An_AffineFold NoIx TxSkelOutReferenceScript ScriptHash
-> TxSkelOutReferenceScript -> Maybe ScriptHash
forall k (is :: IxList) s a.
Is k An_AffineFold =>
Optic' k is s a -> s -> Maybe a
preview Optic' An_AffineFold NoIx TxSkelOutReferenceScript ScriptHash
txSkelOutReferenceScriptHashAF

instance Show TxSkelOutReferenceScript where
  show :: TxSkelOutReferenceScript -> String
show TxSkelOutReferenceScript
refScript =
    String -> (ScriptHash -> String) -> Maybe ScriptHash -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
      String
"No reference script"
      ((String
"Reference script: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<>) ShowS -> (ScriptHash -> String) -> ScriptHash -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScriptHash -> String
forall a. Show a => a -> String
show)
      (Maybe ScriptHash -> String) -> Maybe ScriptHash -> String
forall a b. (a -> b) -> a -> b
$ Optic' An_AffineFold NoIx TxSkelOutReferenceScript ScriptHash
-> TxSkelOutReferenceScript -> Maybe ScriptHash
forall k (is :: IxList) s a.
Is k An_AffineFold =>
Optic' k is s a -> s -> Maybe a
preview Optic' An_AffineFold NoIx TxSkelOutReferenceScript ScriptHash
txSkelOutReferenceScriptHashAF TxSkelOutReferenceScript
refScript

-- | A prism targeting a certain typed reference script within a 'TxSkelOutReferenceScript'
txSkelOutReferenceScriptTypedP :: (ReferenceScriptConstrs a, ReferenceScriptConstrs b) => Prism TxSkelOutReferenceScript TxSkelOutReferenceScript a b
txSkelOutReferenceScriptTypedP :: forall a b.
(ReferenceScriptConstrs a, ReferenceScriptConstrs b) =>
Prism TxSkelOutReferenceScript TxSkelOutReferenceScript a b
txSkelOutReferenceScriptTypedP =
  (b -> TxSkelOutReferenceScript)
-> (TxSkelOutReferenceScript -> Either TxSkelOutReferenceScript a)
-> Prism TxSkelOutReferenceScript TxSkelOutReferenceScript a b
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism
    b -> TxSkelOutReferenceScript
forall a. ReferenceScriptConstrs a => a -> TxSkelOutReferenceScript
SomeTxSkelOutReferenceScript
    ( \TxSkelOutReferenceScript
refScript -> case TxSkelOutReferenceScript
refScript of
        TxSkelOutReferenceScript
NoTxSkelOutReferenceScript -> TxSkelOutReferenceScript -> Either TxSkelOutReferenceScript a
forall a b. a -> Either a b
Left TxSkelOutReferenceScript
refScript
        SomeTxSkelOutReferenceScript 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
refScript) 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 prism targeting the versioned script within a 'TxSkelOutReferenceScript'
txSkelOutReferenceScriptVersionedP :: Prism' TxSkelOutReferenceScript (Script.Versioned Script.Script)
txSkelOutReferenceScriptVersionedP :: Prism' TxSkelOutReferenceScript (Versioned Script)
txSkelOutReferenceScriptVersionedP =
  (Versioned Script -> TxSkelOutReferenceScript)
-> (TxSkelOutReferenceScript
    -> Either TxSkelOutReferenceScript (Versioned Script))
-> Prism' TxSkelOutReferenceScript (Versioned Script)
forall b t s a. (b -> t) -> (s -> Either t a) -> Prism s t a b
prism
    Versioned Script -> TxSkelOutReferenceScript
forall a. ReferenceScriptConstrs a => a -> TxSkelOutReferenceScript
SomeTxSkelOutReferenceScript
    ( \TxSkelOutReferenceScript
refScript -> case TxSkelOutReferenceScript
refScript of
        TxSkelOutReferenceScript
NoTxSkelOutReferenceScript -> TxSkelOutReferenceScript
-> Either TxSkelOutReferenceScript (Versioned Script)
forall a b. a -> Either a b
Left TxSkelOutReferenceScript
refScript
        SomeTxSkelOutReferenceScript a
script -> Versioned Script
-> Either TxSkelOutReferenceScript (Versioned Script)
forall a b. b -> Either a b
Right (a -> Versioned Script
forall s a. ToVersioned s a => a -> Versioned s
Script.toVersioned a
script)
    )

-- | An affine fold producing an optional script hash from a 'TxSkelOutReferenceScript'
txSkelOutReferenceScriptHashAF :: AffineFold TxSkelOutReferenceScript Api.ScriptHash
txSkelOutReferenceScriptHashAF :: Optic' An_AffineFold NoIx TxSkelOutReferenceScript ScriptHash
txSkelOutReferenceScriptHashAF = Prism' TxSkelOutReferenceScript (Versioned Script)
txSkelOutReferenceScriptVersionedP Prism' TxSkelOutReferenceScript (Versioned Script)
-> Optic
     A_Getter
     NoIx
     (Versioned Script)
     (Versioned Script)
     ScriptHash
     ScriptHash
-> Optic' An_AffineFold NoIx TxSkelOutReferenceScript ScriptHash
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
% (Versioned Script -> ScriptHash)
-> Optic
     A_Getter
     NoIx
     (Versioned Script)
     (Versioned Script)
     ScriptHash
     ScriptHash
forall s a. (s -> a) -> Getter s a
to Versioned Script -> ScriptHash
forall a. ToScriptHash a => a -> ScriptHash
Script.toScriptHash