{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Cardano.Api.Experimental.AnyScript
  ( AnyScript (..)
  , deserialiseAnyPlutusScriptOfLanguage
  , deserialiseAnySimpleScript
  , hashAnyScript
  )
where

import Cardano.Api.Experimental.Era
import Cardano.Api.Experimental.Plutus.Internal.Script hiding (AnyPlutusScript)
import Cardano.Api.Experimental.Simple.Script
import Cardano.Api.HasTypeProxy
import Cardano.Api.Ledger.Internal.Reexport qualified as L

import Cardano.Binary qualified as CBOR
import Cardano.Ledger.Core qualified as L
import Cardano.Ledger.Plutus.Language qualified as Plutus

import Data.ByteString qualified as BS

data AnyScript era where
  AnySimpleScript :: SimpleScript era -> AnyScript era
  AnyPlutusScript :: Plutus.PlutusLanguage lang => PlutusScriptInEra lang era -> AnyScript era

hashAnyScript :: forall era. IsEra era => AnyScript (LedgerEra era) -> L.ScriptHash
hashAnyScript :: forall era. IsEra era => AnyScript (LedgerEra era) -> ScriptHash
hashAnyScript (AnySimpleScript SimpleScript (LedgerEra era)
ss) =
  SimpleScript (LedgerEra era) -> ScriptHash
forall era. IsEra era => SimpleScript (LedgerEra era) -> ScriptHash
hashSimpleScript SimpleScript (LedgerEra era)
ss
hashAnyScript (AnyPlutusScript PlutusScriptInEra lang (LedgerEra era)
ps) =
  PlutusScriptInEra lang (LedgerEra era) -> ScriptHash
forall era (lang :: Language).
IsEra era =>
PlutusScriptInEra lang (LedgerEra era) -> ScriptHash
hashPlutusScriptInEra PlutusScriptInEra lang (LedgerEra era)
ps

deserialiseAnySimpleScript
  :: forall era. IsEra era => BS.ByteString -> Either CBOR.DecoderError (AnyScript (LedgerEra era))
deserialiseAnySimpleScript :: forall era.
IsEra era =>
ByteString -> Either DecoderError (AnyScript (LedgerEra era))
deserialiseAnySimpleScript ByteString
bs =
  SimpleScript (LedgerEra era) -> AnyScript (LedgerEra era)
forall era. SimpleScript era -> AnyScript era
AnySimpleScript (SimpleScript (LedgerEra era) -> AnyScript (LedgerEra era))
-> Either DecoderError (SimpleScript (LedgerEra era))
-> Either DecoderError (AnyScript (LedgerEra era))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Era era
-> (EraCommonConstraints era =>
    Either DecoderError (SimpleScript (LedgerEra era)))
-> Either DecoderError (SimpleScript (LedgerEra era))
forall era a. Era era -> (EraCommonConstraints era => a) -> a
obtainCommonConstraints (forall era. IsEra era => Era era
useEra @era) (ByteString -> Either DecoderError (SimpleScript (LedgerEra era))
forall era.
EraScript era =>
ByteString -> Either DecoderError (SimpleScript era)
deserialiseSimpleScript ByteString
bs)

deserialiseAnyPlutusScriptOfLanguage
  :: forall era lang
   . (IsEra era, Plutus.PlutusLanguage lang, HasTypeProxy (Plutus.SLanguage lang))
  => BS.ByteString -> L.SLanguage lang -> Either CBOR.DecoderError (AnyScript (LedgerEra era))
deserialiseAnyPlutusScriptOfLanguage :: forall era (lang :: Language).
(IsEra era, PlutusLanguage lang, HasTypeProxy (SLanguage lang)) =>
ByteString
-> SLanguage lang
-> Either DecoderError (AnyScript (LedgerEra era))
deserialiseAnyPlutusScriptOfLanguage ByteString
bs SLanguage lang
lang = do
  s :: (PlutusScriptInEra lang (LedgerEra era)) <-
    Era era
-> (EraCommonConstraints era =>
    Either DecoderError (PlutusScriptInEra lang (LedgerEra era)))
-> Either DecoderError (PlutusScriptInEra lang (LedgerEra era))
forall era a. Era era -> (EraCommonConstraints era => a) -> a
obtainCommonConstraints (forall era. IsEra era => Era era
useEra @era) (SLanguage lang
-> ByteString
-> Either DecoderError (PlutusScriptInEra lang (LedgerEra era))
forall era (lang :: Language).
(PlutusLanguage lang, HasTypeProxy (SLanguage lang), Era era) =>
SLanguage lang
-> ByteString -> Either DecoderError (PlutusScriptInEra lang era)
deserialisePlutusScriptInEra SLanguage lang
lang ByteString
bs)
  return $ AnyPlutusScript s