-- | Dispatch for running all the CLI commands
module Cardano.CLI.Run
  ( ClientCommand(..)
  , ClientCommandErrors
  , renderClientCommandError
  , runClientCommand
  ) where

import           Cardano.Prelude

import           Control.Monad.Trans.Except.Extra (firstExceptT)
import qualified Data.Text as Text

import           Cardano.CLI.Byron.Commands (ByronCommand)
import           Cardano.CLI.Byron.Run (ByronClientCmdError, renderByronClientCmdError,
                     runByronClientCommand)
import           Cardano.CLI.Shelley.Commands (ShelleyCommand)
import           Cardano.CLI.Shelley.Run (ShelleyClientCmdError, renderShelleyClientCmdError,
                     runShelleyClientCommand)

import           Cardano.Config.Git.Rev (gitRev)
import           Data.Version (showVersion)
import           Paths_cardano_cli (version)
import           System.Info (arch, compilerName, compilerVersion, os)

-- | Sub-commands of 'cardano-cli'.
data ClientCommand =

    -- | Byron Related Commands
    ByronCommand ByronCommand

    -- | Shelley Related Commands
  | ShelleyCommand ShelleyCommand

  | DisplayVersion
  deriving Int -> ClientCommand -> ShowS
[ClientCommand] -> ShowS
ClientCommand -> String
(Int -> ClientCommand -> ShowS)
-> (ClientCommand -> String)
-> ([ClientCommand] -> ShowS)
-> Show ClientCommand
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ClientCommand] -> ShowS
$cshowList :: [ClientCommand] -> ShowS
show :: ClientCommand -> String
$cshow :: ClientCommand -> String
showsPrec :: Int -> ClientCommand -> ShowS
$cshowsPrec :: Int -> ClientCommand -> ShowS
Show

data ClientCommandErrors
  = ByronClientError ByronClientCmdError
  | ShelleyClientError ShelleyCommand ShelleyClientCmdError
  deriving Int -> ClientCommandErrors -> ShowS
[ClientCommandErrors] -> ShowS
ClientCommandErrors -> String
(Int -> ClientCommandErrors -> ShowS)
-> (ClientCommandErrors -> String)
-> ([ClientCommandErrors] -> ShowS)
-> Show ClientCommandErrors
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ClientCommandErrors] -> ShowS
$cshowList :: [ClientCommandErrors] -> ShowS
show :: ClientCommandErrors -> String
$cshow :: ClientCommandErrors -> String
showsPrec :: Int -> ClientCommandErrors -> ShowS
$cshowsPrec :: Int -> ClientCommandErrors -> ShowS
Show
  --TODO: We should include an AgnosticClientError

runClientCommand :: ClientCommand -> ExceptT ClientCommandErrors IO ()
runClientCommand :: ClientCommand -> ExceptT ClientCommandErrors IO ()
runClientCommand (ByronCommand ByronCommand
c) = (ByronClientCmdError -> ClientCommandErrors)
-> ExceptT ByronClientCmdError IO ()
-> ExceptT ClientCommandErrors IO ()
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT ByronClientCmdError -> ClientCommandErrors
ByronClientError (ExceptT ByronClientCmdError IO ()
 -> ExceptT ClientCommandErrors IO ())
-> ExceptT ByronClientCmdError IO ()
-> ExceptT ClientCommandErrors IO ()
forall a b. (a -> b) -> a -> b
$ ByronCommand -> ExceptT ByronClientCmdError IO ()
runByronClientCommand ByronCommand
c
runClientCommand (ShelleyCommand ShelleyCommand
c) = (ShelleyClientCmdError -> ClientCommandErrors)
-> ExceptT ShelleyClientCmdError IO ()
-> ExceptT ClientCommandErrors IO ()
forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> ExceptT x m a -> ExceptT y m a
firstExceptT (ShelleyCommand -> ShelleyClientCmdError -> ClientCommandErrors
ShelleyClientError ShelleyCommand
c) (ExceptT ShelleyClientCmdError IO ()
 -> ExceptT ClientCommandErrors IO ())
-> ExceptT ShelleyClientCmdError IO ()
-> ExceptT ClientCommandErrors IO ()
forall a b. (a -> b) -> a -> b
$ ShelleyCommand -> ExceptT ShelleyClientCmdError IO ()
runShelleyClientCommand ShelleyCommand
c
runClientCommand ClientCommand
DisplayVersion = ExceptT ClientCommandErrors IO ()
runDisplayVersion

renderClientCommandError :: ClientCommandErrors -> Text
renderClientCommandError :: ClientCommandErrors -> Text
renderClientCommandError (ByronClientError ByronClientCmdError
err) =
  ByronClientCmdError -> Text
renderByronClientCmdError ByronClientCmdError
err
renderClientCommandError (ShelleyClientError ShelleyCommand
cmd ShelleyClientCmdError
err) =
  ShelleyCommand -> ShelleyClientCmdError -> Text
renderShelleyClientCmdError ShelleyCommand
cmd ShelleyClientCmdError
err

runDisplayVersion :: ExceptT ClientCommandErrors IO ()
runDisplayVersion :: ExceptT ClientCommandErrors IO ()
runDisplayVersion = do
    IO () -> ExceptT ClientCommandErrors IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> ExceptT ClientCommandErrors IO ())
-> (Text -> IO ()) -> Text -> ExceptT ClientCommandErrors IO ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> IO ()
putTextLn (Text -> ExceptT ClientCommandErrors IO ())
-> Text -> ExceptT ClientCommandErrors IO ()
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
                [ Text
"cardano-cli ", Version -> Text
renderVersion Version
version
                , Text
" - ", String -> Text
Text.pack String
os, Text
"-", String -> Text
Text.pack String
arch
                , Text
" - ", String -> Text
Text.pack String
compilerName, Text
"-", Version -> Text
renderVersion Version
compilerVersion
                , Text
"\ngit rev ", Text
gitRev
                ]
  where
    renderVersion :: Version -> Text
renderVersion = String -> Text
Text.pack (String -> Text) -> (Version -> String) -> Version -> Text
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Version -> String
showVersion