{-# LANGUAGE RankNTypes #-}

module Cardano.CLI.EraIndependent.Cip.Cip129.Run
  ( runCip129
  )
where

import Cardano.Api hiding (Cip129)

import Cardano.CLI.Compatible.Exception
import Cardano.CLI.EraIndependent.Cip.Cip129.Command
import Cardano.CLI.EraIndependent.Cip.Cip129.Internal.Conversion
import Cardano.CLI.EraIndependent.Cip.Common
import Cardano.CLI.Orphan ()
import Cardano.CLI.Read
import Cardano.CLI.Read.Committee.ColdKey
import Cardano.CLI.Read.Committee.HotKey
import Cardano.CLI.Read.DRep
import Cardano.CLI.Read.GovernanceActionId

import Data.ByteString (ByteString)
import Data.ByteString qualified as BS
import Data.ByteString.Char8 qualified as BSC
import Data.Text.Encoding qualified as Text
import Data.Validation qualified as Valid
import System.IO

runCip129 :: Cip129 -> CIO e ()
runCip129 :: forall e. Cip129 -> CIO e ()
runCip129 (Cip129DRep Input
inp Output
out) = do
  k <- case Input
inp of
    InputTextEnvelopeFile (File String
textEnvFp) -> do
      f <- IO FileOrPipe -> RIO e FileOrPipe
forall a. IO a -> RIO e a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO FileOrPipe -> RIO e FileOrPipe)
-> IO FileOrPipe -> RIO e FileOrPipe
forall a b. (a -> b) -> a -> b
$ String -> IO FileOrPipe
fileOrPipe String
textEnvFp
      fromEitherIOCli $ readDrepVerificationKeyFile f
    InputHexText Text
t -> do
      Either [RawBytesHexError] AnyDrepVerificationKey
-> RIO e AnyDrepVerificationKey
forall e (m :: * -> *) a.
(HasCallStack, MonadIO m, Show e, Typeable e, Error e) =>
Either e a -> m a
fromEitherCli (Either [RawBytesHexError] AnyDrepVerificationKey
 -> RIO e AnyDrepVerificationKey)
-> (Validation [RawBytesHexError] AnyDrepVerificationKey
    -> Either [RawBytesHexError] AnyDrepVerificationKey)
-> Validation [RawBytesHexError] AnyDrepVerificationKey
-> RIO e AnyDrepVerificationKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Validation [RawBytesHexError] AnyDrepVerificationKey
-> Either [RawBytesHexError] AnyDrepVerificationKey
forall e a. Validation e a -> Either e a
Valid.toEither (Validation [RawBytesHexError] AnyDrepVerificationKey
 -> RIO e AnyDrepVerificationKey)
-> Validation [RawBytesHexError] AnyDrepVerificationKey
-> RIO e AnyDrepVerificationKey
forall a b. (a -> b) -> a -> b
$ Text -> Validation [RawBytesHexError] AnyDrepVerificationKey
readDRepHexVerificationKeyText Text
t
    InputBech32Text Text
t -> do
      Either [Bech32DecodeError] AnyDrepVerificationKey
-> RIO e AnyDrepVerificationKey
forall e (m :: * -> *) a.
(HasCallStack, MonadIO m, Show e, Typeable e, Error e) =>
Either e a -> m a
fromEitherCli (Either [Bech32DecodeError] AnyDrepVerificationKey
 -> RIO e AnyDrepVerificationKey)
-> (Validation [Bech32DecodeError] AnyDrepVerificationKey
    -> Either [Bech32DecodeError] AnyDrepVerificationKey)
-> Validation [Bech32DecodeError] AnyDrepVerificationKey
-> RIO e AnyDrepVerificationKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Validation [Bech32DecodeError] AnyDrepVerificationKey
-> Either [Bech32DecodeError] AnyDrepVerificationKey
forall e a. Validation e a -> Either e a
Valid.toEither (Validation [Bech32DecodeError] AnyDrepVerificationKey
 -> RIO e AnyDrepVerificationKey)
-> Validation [Bech32DecodeError] AnyDrepVerificationKey
-> RIO e AnyDrepVerificationKey
forall a b. (a -> b) -> a -> b
$ Text -> Validation [Bech32DecodeError] AnyDrepVerificationKey
readDRepBech32VerificationKeyText Text
t
  let cip129Output = Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ AnyDrepVerificationKey -> Text
encodeCip129DrepVerficationKeyText AnyDrepVerificationKey
k
  renderOutput cip129Output out
runCip129 (Cip129CommitteeHotKey Input
inp Output
out) = do
  k <- case Input
inp of
    InputTextEnvelopeFile (File String
textEnvFp) -> do
      f <- IO FileOrPipe -> RIO e FileOrPipe
forall a. IO a -> RIO e a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO FileOrPipe -> RIO e FileOrPipe)
-> IO FileOrPipe -> RIO e FileOrPipe
forall a b. (a -> b) -> a -> b
$ String -> IO FileOrPipe
fileOrPipe String
textEnvFp
      fromEitherIOCli $ readCommitteeHotVerificationKeyFile f
    InputHexText Text
t ->
      Either [RawBytesHexError] AnyCommitteeHotVerificationKey
-> RIO e AnyCommitteeHotVerificationKey
forall e (m :: * -> *) a.
(HasCallStack, MonadIO m, Show e, Typeable e, Error e) =>
Either e a -> m a
fromEitherCli (Either [RawBytesHexError] AnyCommitteeHotVerificationKey
 -> RIO e AnyCommitteeHotVerificationKey)
-> (Validation [RawBytesHexError] AnyCommitteeHotVerificationKey
    -> Either [RawBytesHexError] AnyCommitteeHotVerificationKey)
-> Validation [RawBytesHexError] AnyCommitteeHotVerificationKey
-> RIO e AnyCommitteeHotVerificationKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Validation [RawBytesHexError] AnyCommitteeHotVerificationKey
-> Either [RawBytesHexError] AnyCommitteeHotVerificationKey
forall e a. Validation e a -> Either e a
Valid.toEither (Validation [RawBytesHexError] AnyCommitteeHotVerificationKey
 -> RIO e AnyCommitteeHotVerificationKey)
-> Validation [RawBytesHexError] AnyCommitteeHotVerificationKey
-> RIO e AnyCommitteeHotVerificationKey
forall a b. (a -> b) -> a -> b
$ Text
-> Validation [RawBytesHexError] AnyCommitteeHotVerificationKey
readCommitteeHotHexVerificationKeyText Text
t
    InputBech32Text Text
t ->
      Either [Bech32DecodeError] AnyCommitteeHotVerificationKey
-> RIO e AnyCommitteeHotVerificationKey
forall e (m :: * -> *) a.
(HasCallStack, MonadIO m, Show e, Typeable e, Error e) =>
Either e a -> m a
fromEitherCli (Either [Bech32DecodeError] AnyCommitteeHotVerificationKey
 -> RIO e AnyCommitteeHotVerificationKey)
-> (Validation [Bech32DecodeError] AnyCommitteeHotVerificationKey
    -> Either [Bech32DecodeError] AnyCommitteeHotVerificationKey)
-> Validation [Bech32DecodeError] AnyCommitteeHotVerificationKey
-> RIO e AnyCommitteeHotVerificationKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Validation [Bech32DecodeError] AnyCommitteeHotVerificationKey
-> Either [Bech32DecodeError] AnyCommitteeHotVerificationKey
forall e a. Validation e a -> Either e a
Valid.toEither (Validation [Bech32DecodeError] AnyCommitteeHotVerificationKey
 -> RIO e AnyCommitteeHotVerificationKey)
-> Validation [Bech32DecodeError] AnyCommitteeHotVerificationKey
-> RIO e AnyCommitteeHotVerificationKey
forall a b. (a -> b) -> a -> b
$ Text
-> Validation [Bech32DecodeError] AnyCommitteeHotVerificationKey
readCommitteeHotBech32VerificationKeyText Text
t
  let cip129Output = Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ AnyCommitteeHotVerificationKey -> Text
encodeCip129CommitteeHotVerficationKeyText AnyCommitteeHotVerificationKey
k
  renderOutput cip129Output out
runCip129 (Cip129CommitteeColdKey Input
inp Output
out) = do
  k <- case Input
inp of
    InputTextEnvelopeFile (File String
textEnvFp) -> do
      f <- IO FileOrPipe -> RIO e FileOrPipe
forall a. IO a -> RIO e a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO FileOrPipe -> RIO e FileOrPipe)
-> IO FileOrPipe -> RIO e FileOrPipe
forall a b. (a -> b) -> a -> b
$ String -> IO FileOrPipe
fileOrPipe String
textEnvFp
      fromEitherIOCli $ readCommitteeColdVerificationKeyFile f
    InputHexText Text
t ->
      Either [RawBytesHexError] AnyCommitteeColdVerificationKey
-> RIO e AnyCommitteeColdVerificationKey
forall e (m :: * -> *) a.
(HasCallStack, MonadIO m, Show e, Typeable e, Error e) =>
Either e a -> m a
fromEitherCli (Either [RawBytesHexError] AnyCommitteeColdVerificationKey
 -> RIO e AnyCommitteeColdVerificationKey)
-> (Validation [RawBytesHexError] AnyCommitteeColdVerificationKey
    -> Either [RawBytesHexError] AnyCommitteeColdVerificationKey)
-> Validation [RawBytesHexError] AnyCommitteeColdVerificationKey
-> RIO e AnyCommitteeColdVerificationKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Validation [RawBytesHexError] AnyCommitteeColdVerificationKey
-> Either [RawBytesHexError] AnyCommitteeColdVerificationKey
forall e a. Validation e a -> Either e a
Valid.toEither (Validation [RawBytesHexError] AnyCommitteeColdVerificationKey
 -> RIO e AnyCommitteeColdVerificationKey)
-> Validation [RawBytesHexError] AnyCommitteeColdVerificationKey
-> RIO e AnyCommitteeColdVerificationKey
forall a b. (a -> b) -> a -> b
$ Text
-> Validation [RawBytesHexError] AnyCommitteeColdVerificationKey
readCommitteeColdHexVerificationKeyText Text
t
    InputBech32Text Text
t ->
      Either [Bech32DecodeError] AnyCommitteeColdVerificationKey
-> RIO e AnyCommitteeColdVerificationKey
forall e (m :: * -> *) a.
(HasCallStack, MonadIO m, Show e, Typeable e, Error e) =>
Either e a -> m a
fromEitherCli (Either [Bech32DecodeError] AnyCommitteeColdVerificationKey
 -> RIO e AnyCommitteeColdVerificationKey)
-> (Validation [Bech32DecodeError] AnyCommitteeColdVerificationKey
    -> Either [Bech32DecodeError] AnyCommitteeColdVerificationKey)
-> Validation [Bech32DecodeError] AnyCommitteeColdVerificationKey
-> RIO e AnyCommitteeColdVerificationKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Validation [Bech32DecodeError] AnyCommitteeColdVerificationKey
-> Either [Bech32DecodeError] AnyCommitteeColdVerificationKey
forall e a. Validation e a -> Either e a
Valid.toEither (Validation [Bech32DecodeError] AnyCommitteeColdVerificationKey
 -> RIO e AnyCommitteeColdVerificationKey)
-> Validation [Bech32DecodeError] AnyCommitteeColdVerificationKey
-> RIO e AnyCommitteeColdVerificationKey
forall a b. (a -> b) -> a -> b
$ Text
-> Validation [Bech32DecodeError] AnyCommitteeColdVerificationKey
readCommitteeColdBech32VerificationKeyText Text
t
  let cip129Output = Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ AnyCommitteeColdVerificationKey -> Text
encodeCip129CommitteeColdVerficationKeyText AnyCommitteeColdVerificationKey
k
  renderOutput cip129Output out
runCip129 (Cip129GovernanceAction Input
inp Output
out) =
  case Input
inp of
    InputHexText Text
t -> do
      govId <- Either String GovActionId -> RIO e GovActionId
forall e (m :: * -> *) a.
(HasCallStack, MonadIO m, Show e, Typeable e, Error e) =>
Either e a -> m a
fromEitherCli (Either String GovActionId -> RIO e GovActionId)
-> Either String GovActionId -> RIO e GovActionId
forall a b. (a -> b) -> a -> b
$ Text -> Either String GovActionId
readGoveranceActionIdHexText Text
t
      let cip129Output = Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ GovActionId -> Text
encodeCip129GovernanceActionIdText GovActionId
govId
      renderOutput cip129Output out
    InputBech32Text{} ->
      InputError -> RIO e ()
forall e (m :: * -> *) a.
(HasCallStack, Show e, Typeable e, Error e, MonadIO m) =>
e -> m a
throwCliError (InputError -> RIO e ()) -> InputError -> RIO e ()
forall a b. (a -> b) -> a -> b
$ Text -> InputError
InputError Text
"Bech32 encoded Governance Action Id is not supported"
    InputTextEnvelopeFile{} ->
      InputError -> RIO e ()
forall e (m :: * -> *) a.
(HasCallStack, Show e, Typeable e, Error e, MonadIO m) =>
e -> m a
throwCliError (InputError -> RIO e ()) -> InputError -> RIO e ()
forall a b. (a -> b) -> a -> b
$ Text -> InputError
InputError Text
"TextEnvelope encoded Governance Action Id is not supported"

renderOutput :: ByteString -> Output -> CIO e ()
renderOutput :: forall e. ByteString -> Output -> CIO e ()
renderOutput ByteString
cip129Output Output
out = case Output
out of
  Output
OutputText -> do
    IO () -> RIO e ()
forall a. IO a -> RIO e a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> RIO e ()) -> IO () -> RIO e ()
forall a b. (a -> b) -> a -> b
$ Handle -> ByteString -> IO ()
BSC.hPutStrLn Handle
stdout ByteString
cip129Output
  OutputFile (File String
fp) -> do
    IO () -> RIO e ()
forall a. IO a -> RIO e a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> RIO e ()) -> IO () -> RIO e ()
forall a b. (a -> b) -> a -> b
$ String -> ByteString -> IO ()
BS.writeFile String
fp ByteString
cip129Output