{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}

module Test.Cardano.Ledger.Conway.Spec (spec) where

import Cardano.Ledger.Conway.Core
import Cardano.Ledger.Conway.Rules (
  ConwayEpochEvent,
  ConwayHardForkEvent,
  ConwayNewEpochEvent,
 )
import Cardano.Ledger.Plutus.Language (SLanguage (..))
import Control.State.Transition (STS (..))
import qualified Test.Cardano.Ledger.Alonzo.Binary.CostModelsSpec as CostModelsSpec
import qualified Test.Cardano.Ledger.Alonzo.Binary.TxWitsSpec as TxWitsSpec
import qualified Test.Cardano.Ledger.Babbage.TxInfoSpec as BabbageTxInfo
import Test.Cardano.Ledger.Common
import qualified Test.Cardano.Ledger.Conway.Binary.Regression as Regression
import qualified Test.Cardano.Ledger.Conway.BinarySpec as Binary
import qualified Test.Cardano.Ledger.Conway.CommitteeRatifySpec as CommitteeRatify
import qualified Test.Cardano.Ledger.Conway.DRepRatifySpec as DRepRatify
import qualified Test.Cardano.Ledger.Conway.Imp as Imp
import Test.Cardano.Ledger.Conway.ImpTest (ConwayEraImp, EraSpecificSpec)
import qualified Test.Cardano.Ledger.Conway.Proposals as Proposals
import qualified Test.Cardano.Ledger.Conway.SPORatifySpec as SPORatifySpec
import Test.Cardano.Ledger.Core.Binary.RoundTrip (RuleListEra)
import Test.Cardano.Ledger.Core.JSON (roundTripJsonEraSpec)

spec ::
  forall era.
  ( RuleListEra era
  , ConwayEraImp era
  , EraSpecificSpec era
  , Event (EraRule "HARDFORK" era) ~ ConwayHardForkEvent era
  , Event (EraRule "EPOCH" era) ~ ConwayEpochEvent era
  , Event (EraRule "NEWEPOCH" era) ~ ConwayNewEpochEvent era
  ) =>
  Spec
spec :: forall era.
(RuleListEra era, ConwayEraImp era, EraSpecificSpec era,
 Event (EraRule "HARDFORK" era) ~ ConwayHardForkEvent era,
 Event (EraRule "EPOCH" era) ~ ConwayEpochEvent era,
 Event (EraRule "NEWEPOCH" era) ~ ConwayNewEpochEvent era) =>
Spec
spec =
  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"Conway features" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    forall era. ConwayEraTest era => Spec
Proposals.spec @era
    forall era. (ConwayEraImp era, RuleListEra era) => Spec
Binary.spec @era
    forall era. ConwayEraTest era => Spec
DRepRatify.spec @era
    forall era. ConwayEraTest era => Spec
CommitteeRatify.spec @era
    forall era. ConwayEraTest era => Spec
SPORatifySpec.spec @era
    forall era. (HasCallStack, EraTest era) => Spec
roundTripJsonEraSpec @era
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"Imp" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      forall era.
(ConwayEraImp era, EraSpecificSpec era,
 Event (EraRule "HARDFORK" era) ~ ConwayHardForkEvent era,
 Event (EraRule "EPOCH" era) ~ ConwayEpochEvent era,
 Event (EraRule "NEWEPOCH" era) ~ ConwayNewEpochEvent era) =>
Spec
Imp.spec @era
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"CostModels" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      forall era. (AlonzoEraPParams era, AlonzoEraScript era) => Spec
CostModelsSpec.spec @era
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"TxWits" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      forall era.
(EraPlutusContext era, Arbitrary (NativeScript era)) =>
Spec
TxWitsSpec.spec @era
    forall era. EraTx era => Spec
Regression.spec @era
    String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"TxInfo" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
      forall era.
(EraTx era, BabbageEraTxBody era, Value era ~ MaryValue,
 Inject (BabbageContextError era) (ContextError era),
 EraPlutusTxInfo 'PlutusV1 era, EraPlutusTxInfo 'PlutusV2 era) =>
Spec
BabbageTxInfo.spec @era
      String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"PlutusV3" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$
        forall era (l :: Language).
(EraTx era, EraPlutusTxInfo l era, EraPlutusTxInfo 'PlutusV2 era,
 BabbageEraTxBody era, Value era ~ MaryValue,
 Inject (BabbageContextError era) (ContextError era),
 Show (PlutusTxInInfo era l), Eq (PlutusTxInInfo era l)) =>
SLanguage l -> Spec
BabbageTxInfo.txInfoSpec @era SLanguage 'PlutusV3
SPlutusV3