{-# 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
  AnyDrepVerificationKey
k <- case Input
inp of
    InputTextEnvelopeFile (File String
textEnvFp) -> do
      FileOrPipe
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
      IO (Either (FileError TextEnvelopeError) AnyDrepVerificationKey)
-> RIO e AnyDrepVerificationKey
forall e (m :: * -> *) a.
(HasCallStack, MonadIO m, Show e, Typeable e, Error e) =>
IO (Either e a) -> m a
fromEitherIOCli (IO (Either (FileError TextEnvelopeError) AnyDrepVerificationKey)
 -> RIO e AnyDrepVerificationKey)
-> IO (Either (FileError TextEnvelopeError) AnyDrepVerificationKey)
-> RIO e AnyDrepVerificationKey
forall a b. (a -> b) -> a -> b
$ FileOrPipe
-> IO (Either (FileError TextEnvelopeError) AnyDrepVerificationKey)
readDrepVerificationKeyFile FileOrPipe
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 :: ByteString
cip129Output = Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ AnyDrepVerificationKey -> Text
encodeCip129DrepVerficationKeyText AnyDrepVerificationKey
k
  ByteString -> Output -> CIO e ()
forall e. ByteString -> Output -> CIO e ()
renderOutput ByteString
cip129Output Output
out
runCip129 (Cip129CommitteeHotKey Input
inp Output
out) = do
  AnyCommitteeHotVerificationKey
k <- case Input
inp of
    InputTextEnvelopeFile (File String
textEnvFp) -> do
      FileOrPipe
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
      IO
  (Either
     (FileError TextEnvelopeError) AnyCommitteeHotVerificationKey)
-> RIO e AnyCommitteeHotVerificationKey
forall e (m :: * -> *) a.
(HasCallStack, MonadIO m, Show e, Typeable e, Error e) =>
IO (Either e a) -> m a
fromEitherIOCli (IO
   (Either
      (FileError TextEnvelopeError) AnyCommitteeHotVerificationKey)
 -> RIO e AnyCommitteeHotVerificationKey)
-> IO
     (Either
        (FileError TextEnvelopeError) AnyCommitteeHotVerificationKey)
-> RIO e AnyCommitteeHotVerificationKey
forall a b. (a -> b) -> a -> b
$ FileOrPipe
-> IO
     (Either
        (FileError TextEnvelopeError) AnyCommitteeHotVerificationKey)
readCommitteeHotVerificationKeyFile FileOrPipe
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 :: ByteString
cip129Output = Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ AnyCommitteeHotVerificationKey -> Text
encodeCip129CommitteeHotVerficationKeyText AnyCommitteeHotVerificationKey
k
  ByteString -> Output -> CIO e ()
forall e. ByteString -> Output -> CIO e ()
renderOutput ByteString
cip129Output Output
out
runCip129 (Cip129CommitteeColdKey Input
inp Output
out) = do
  AnyCommitteeColdVerificationKey
k <- case Input
inp of
    InputTextEnvelopeFile (File String
textEnvFp) -> do
      FileOrPipe
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
      IO
  (Either
     (FileError TextEnvelopeError) AnyCommitteeColdVerificationKey)
-> RIO e AnyCommitteeColdVerificationKey
forall e (m :: * -> *) a.
(HasCallStack, MonadIO m, Show e, Typeable e, Error e) =>
IO (Either e a) -> m a
fromEitherIOCli (IO
   (Either
      (FileError TextEnvelopeError) AnyCommitteeColdVerificationKey)
 -> RIO e AnyCommitteeColdVerificationKey)
-> IO
     (Either
        (FileError TextEnvelopeError) AnyCommitteeColdVerificationKey)
-> RIO e AnyCommitteeColdVerificationKey
forall a b. (a -> b) -> a -> b
$ FileOrPipe
-> IO
     (Either
        (FileError TextEnvelopeError) AnyCommitteeColdVerificationKey)
readCommitteeColdVerificationKeyFile FileOrPipe
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 :: ByteString
cip129Output = Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ AnyCommitteeColdVerificationKey -> Text
encodeCip129CommitteeColdVerficationKeyText AnyCommitteeColdVerificationKey
k
  ByteString -> Output -> CIO e ()
forall e. ByteString -> Output -> CIO e ()
renderOutput ByteString
cip129Output Output
out
runCip129 (Cip129GovernanceAction Input
inp Output
out) =
  case Input
inp of
    InputHexText Text
t -> do
      GovActionId
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 :: ByteString
cip129Output = Text -> ByteString
Text.encodeUtf8 (Text -> ByteString) -> Text -> ByteString
forall a b. (a -> b) -> a -> b
$ GovActionId -> Text
encodeCip129GovernanceActionIdText GovActionId
govId
      ByteString -> Output -> CIO e ()
forall e. ByteString -> Output -> CIO e ()
renderOutput ByteString
cip129Output Output
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