{-# LANGUAGE TypeApplications #-}

module Testnet.Commands.Cardano
  ( CardanoOptions(..)
  , cmdCardano
  , runCardanoOptions
  ) where

import           GHC.Enum
import           Data.Eq
import           Data.Function
import           Data.Int
import           Data.Maybe
import           Data.Semigroup
import           Options.Applicative
import           System.IO (IO)
import           Testnet.Cardano
import           Testnet.Run (runTestnet)
import           Text.Read
import           Text.Show

import qualified Options.Applicative as OA

data CardanoOptions = CardanoOptions
  { CardanoOptions -> Maybe Int
maybeTestnetMagic :: Maybe Int
  , CardanoOptions -> TestnetOptions
testnetOptions :: TestnetOptions
  } deriving (CardanoOptions -> CardanoOptions -> Bool
(CardanoOptions -> CardanoOptions -> Bool)
-> (CardanoOptions -> CardanoOptions -> Bool) -> Eq CardanoOptions
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CardanoOptions -> CardanoOptions -> Bool
$c/= :: CardanoOptions -> CardanoOptions -> Bool
== :: CardanoOptions -> CardanoOptions -> Bool
$c== :: CardanoOptions -> CardanoOptions -> Bool
Eq, Int -> CardanoOptions -> ShowS
[CardanoOptions] -> ShowS
CardanoOptions -> String
(Int -> CardanoOptions -> ShowS)
-> (CardanoOptions -> String)
-> ([CardanoOptions] -> ShowS)
-> Show CardanoOptions
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CardanoOptions] -> ShowS
$cshowList :: [CardanoOptions] -> ShowS
show :: CardanoOptions -> String
$cshow :: CardanoOptions -> String
showsPrec :: Int -> CardanoOptions -> ShowS
$cshowsPrec :: Int -> CardanoOptions -> ShowS
Show)

optsTestnet :: Parser TestnetOptions
optsTestnet :: Parser TestnetOptions
optsTestnet = Int -> Int -> Era -> Int -> Double -> Double -> TestnetOptions
TestnetOptions
  (Int -> Int -> Era -> Int -> Double -> Double -> TestnetOptions)
-> Parser Int
-> Parser (Int -> Era -> Int -> Double -> Double -> TestnetOptions)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadM Int -> Mod OptionFields Int -> Parser Int
forall a. ReadM a -> Mod OptionFields a -> Parser a
OA.option ReadM Int
forall a. Read a => ReadM a
auto
      (   String -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => String -> Mod f a
OA.long String
"num-bft-nodes"
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Int
forall (f :: * -> *) a. String -> Mod f a
OA.help String
"Number of BFT nodes"
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Int
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
OA.metavar String
"COUNT"
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  Mod OptionFields Int
forall a (f :: * -> *). Show a => Mod f a
OA.showDefault
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  Int -> Mod OptionFields Int
forall (f :: * -> *) a. HasValue f => a -> Mod f a
OA.value (TestnetOptions -> Int
numBftNodes TestnetOptions
defaultTestnetOptions)
      )
  Parser (Int -> Era -> Int -> Double -> Double -> TestnetOptions)
-> Parser Int
-> Parser (Era -> Int -> Double -> Double -> TestnetOptions)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Int -> Mod OptionFields Int -> Parser Int
forall a. ReadM a -> Mod OptionFields a -> Parser a
OA.option ReadM Int
forall a. Read a => ReadM a
auto
      (   String -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => String -> Mod f a
OA.long String
"num-pool-nodes"
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Int
forall (f :: * -> *) a. String -> Mod f a
OA.help String
"Number of pool nodes"
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Int
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
OA.metavar String
"COUNT"
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  Mod OptionFields Int
forall a (f :: * -> *). Show a => Mod f a
OA.showDefault
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  Int -> Mod OptionFields Int
forall (f :: * -> *) a. HasValue f => a -> Mod f a
OA.value (TestnetOptions -> Int
numPoolNodes TestnetOptions
defaultTestnetOptions)
      )
  Parser (Era -> Int -> Double -> Double -> TestnetOptions)
-> Parser Era -> Parser (Int -> Double -> Double -> TestnetOptions)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Era -> Mod OptionFields Era -> Parser Era
forall a. ReadM a -> Mod OptionFields a -> Parser a
OA.option ((String -> Either String Era) -> ReadM Era
forall a. (String -> Either String a) -> ReadM a
OA.eitherReader String -> Either String Era
forall a. Read a => String -> Either String a
readEither)
      (   String -> Mod OptionFields Era
forall (f :: * -> *) a. HasName f => String -> Mod f a
OA.long String
"era"
      Mod OptionFields Era
-> Mod OptionFields Era -> Mod OptionFields Era
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Era
forall (f :: * -> *) a. String -> Mod f a
OA.help (String
"Era to upgrade to.  " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> [Era] -> String
forall a. Show a => a -> String
show @[Era] [Era
forall a. Bounded a => a
minBound .. Era
forall a. Bounded a => a
maxBound])
      Mod OptionFields Era
-> Mod OptionFields Era -> Mod OptionFields Era
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Era
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
OA.metavar String
"ERA"
      Mod OptionFields Era
-> Mod OptionFields Era -> Mod OptionFields Era
forall a. Semigroup a => a -> a -> a
<>  Mod OptionFields Era
forall a (f :: * -> *). Show a => Mod f a
OA.showDefault
      Mod OptionFields Era
-> Mod OptionFields Era -> Mod OptionFields Era
forall a. Semigroup a => a -> a -> a
<>  Era -> Mod OptionFields Era
forall (f :: * -> *) a. HasValue f => a -> Mod f a
OA.value (TestnetOptions -> Era
era TestnetOptions
defaultTestnetOptions)
      )
  Parser (Int -> Double -> Double -> TestnetOptions)
-> Parser Int -> Parser (Double -> Double -> TestnetOptions)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Int -> Mod OptionFields Int -> Parser Int
forall a. ReadM a -> Mod OptionFields a -> Parser a
OA.option ReadM Int
forall a. Read a => ReadM a
auto
      (   String -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => String -> Mod f a
OA.long String
"epoch-length"
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Int
forall (f :: * -> *) a. String -> Mod f a
OA.help String
"Epoch length"
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Int
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
OA.metavar String
"MILLISECONDS"
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  Mod OptionFields Int
forall a (f :: * -> *). Show a => Mod f a
OA.showDefault
      Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  Int -> Mod OptionFields Int
forall (f :: * -> *) a. HasValue f => a -> Mod f a
OA.value (TestnetOptions -> Int
epochLength TestnetOptions
defaultTestnetOptions)
      )
  Parser (Double -> Double -> TestnetOptions)
-> Parser Double -> Parser (Double -> TestnetOptions)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Double -> Mod OptionFields Double -> Parser Double
forall a. ReadM a -> Mod OptionFields a -> Parser a
OA.option ReadM Double
forall a. Read a => ReadM a
auto
      (   String -> Mod OptionFields Double
forall (f :: * -> *) a. HasName f => String -> Mod f a
OA.long String
"slot-length"
      Mod OptionFields Double
-> Mod OptionFields Double -> Mod OptionFields Double
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Double
forall (f :: * -> *) a. String -> Mod f a
OA.help String
"Slot length"
      Mod OptionFields Double
-> Mod OptionFields Double -> Mod OptionFields Double
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Double
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
OA.metavar String
"SECONDS"
      Mod OptionFields Double
-> Mod OptionFields Double -> Mod OptionFields Double
forall a. Semigroup a => a -> a -> a
<>  Mod OptionFields Double
forall a (f :: * -> *). Show a => Mod f a
OA.showDefault
      Mod OptionFields Double
-> Mod OptionFields Double -> Mod OptionFields Double
forall a. Semigroup a => a -> a -> a
<>  Double -> Mod OptionFields Double
forall (f :: * -> *) a. HasValue f => a -> Mod f a
OA.value (TestnetOptions -> Double
slotLength TestnetOptions
defaultTestnetOptions)
      )
  Parser (Double -> TestnetOptions)
-> Parser Double -> Parser TestnetOptions
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadM Double -> Mod OptionFields Double -> Parser Double
forall a. ReadM a -> Mod OptionFields a -> Parser a
OA.option ReadM Double
forall a. Read a => ReadM a
auto
      (   String -> Mod OptionFields Double
forall (f :: * -> *) a. HasName f => String -> Mod f a
OA.long String
"active-slots-coeff"
      Mod OptionFields Double
-> Mod OptionFields Double -> Mod OptionFields Double
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Double
forall (f :: * -> *) a. String -> Mod f a
OA.help String
"Active slots co-efficient"
      Mod OptionFields Double
-> Mod OptionFields Double -> Mod OptionFields Double
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Double
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
OA.metavar String
"DOUBLE"
      Mod OptionFields Double
-> Mod OptionFields Double -> Mod OptionFields Double
forall a. Semigroup a => a -> a -> a
<>  Mod OptionFields Double
forall a (f :: * -> *). Show a => Mod f a
OA.showDefault
      Mod OptionFields Double
-> Mod OptionFields Double -> Mod OptionFields Double
forall a. Semigroup a => a -> a -> a
<>  Double -> Mod OptionFields Double
forall (f :: * -> *) a. HasValue f => a -> Mod f a
OA.value (TestnetOptions -> Double
activeSlotsCoeff TestnetOptions
defaultTestnetOptions)
      )

optsCardano :: Parser CardanoOptions
optsCardano :: Parser CardanoOptions
optsCardano = Maybe Int -> TestnetOptions -> CardanoOptions
CardanoOptions
  (Maybe Int -> TestnetOptions -> CardanoOptions)
-> Parser (Maybe Int) -> Parser (TestnetOptions -> CardanoOptions)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Int -> Parser (Maybe Int)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional
      ( ReadM Int -> Mod OptionFields Int -> Parser Int
forall a. ReadM a -> Mod OptionFields a -> Parser a
OA.option ReadM Int
forall a. Read a => ReadM a
auto
        (   String -> Mod OptionFields Int
forall (f :: * -> *) a. HasName f => String -> Mod f a
long String
"testnet-magic"
        Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Int
forall (f :: * -> *) a. String -> Mod f a
help String
"Testnet magic"
        Mod OptionFields Int
-> Mod OptionFields Int -> Mod OptionFields Int
forall a. Semigroup a => a -> a -> a
<>  String -> Mod OptionFields Int
forall (f :: * -> *) a. HasMetavar f => String -> Mod f a
metavar String
"INT"
        )
      )
  Parser (TestnetOptions -> CardanoOptions)
-> Parser TestnetOptions -> Parser CardanoOptions
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser TestnetOptions
optsTestnet

runCardanoOptions :: CardanoOptions -> IO ()
runCardanoOptions :: CardanoOptions -> IO ()
runCardanoOptions CardanoOptions
options = Maybe Int -> (Conf -> Integration TestnetRuntime) -> IO ()
forall a. Maybe Int -> (Conf -> Integration a) -> IO ()
runTestnet (CardanoOptions -> Maybe Int
maybeTestnetMagic CardanoOptions
options) ((Conf -> Integration TestnetRuntime) -> IO ())
-> (Conf -> Integration TestnetRuntime) -> IO ()
forall a b. (a -> b) -> a -> b
$
  TestnetOptions -> Conf -> Integration TestnetRuntime
Testnet.Cardano.testnet (CardanoOptions -> TestnetOptions
testnetOptions CardanoOptions
options)

cmdCardano :: Mod CommandFields (IO ())
cmdCardano :: Mod CommandFields (IO ())
cmdCardano = String -> ParserInfo (IO ()) -> Mod CommandFields (IO ())
forall a. String -> ParserInfo a -> Mod CommandFields a
command String
"cardano"  (ParserInfo (IO ()) -> Mod CommandFields (IO ()))
-> ParserInfo (IO ()) -> Mod CommandFields (IO ())
forall a b. (a -> b) -> a -> b
$ (Parser (IO ()) -> InfoMod (IO ()) -> ParserInfo (IO ()))
-> InfoMod (IO ()) -> Parser (IO ()) -> ParserInfo (IO ())
forall a b c. (a -> b -> c) -> b -> a -> c
flip Parser (IO ()) -> InfoMod (IO ()) -> ParserInfo (IO ())
forall a. Parser a -> InfoMod a -> ParserInfo a
info InfoMod (IO ())
forall m. Monoid m => m
idm (Parser (IO ()) -> ParserInfo (IO ()))
-> Parser (IO ()) -> ParserInfo (IO ())
forall a b. (a -> b) -> a -> b
$ CardanoOptions -> IO ()
runCardanoOptions (CardanoOptions -> IO ())
-> Parser CardanoOptions -> Parser (IO ())
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser CardanoOptions
optsCardano