-- | This module defines pretty-printing options for 'prettyCookedOpt' and their
-- default values.
module Cooked.Pretty.Options
  ( PrettyCookedOpts (..),
    PrettyCookedHashOpts (..),
    PCOptTxOutRefs (..),
    hashNamesFromList,
    defaultHashNames,
  )
where

import Cooked.Conversion.ToHash
import Cooked.Currencies (permanentCurrencySymbol, quickCurrencySymbol)
import Cooked.Wallet (wallet)
import Data.Bifunctor (first)
import Data.Default
import Data.Map (Map)
import Data.Map qualified as Map
import PlutusLedgerApi.V3 qualified as Api

data PrettyCookedOpts = PrettyCookedOpts
  { -- | Whether to print transaction ids of validated transactions. By
    -- default: False
    PrettyCookedOpts -> Bool
pcOptPrintTxHashes :: Bool,
    -- | Whether to print transaction outputs references. By default: hidden
    PrettyCookedOpts -> PCOptTxOutRefs
pcOptPrintTxOutRefs :: PCOptTxOutRefs,
    -- | Whether to print tx options that have not been modified from their
    -- default. By default: False
    PrettyCookedOpts -> Bool
pcOptPrintDefaultTxOpts :: Bool,
    -- | Whether to print big integers with numeric underscores. For example
    -- @53_000_000@ instead of @53000000@. By default: True
    PrettyCookedOpts -> Bool
pcOptNumericUnderscores :: Bool,
    -- | Options related to printing hashes
    PrettyCookedOpts -> PrettyCookedHashOpts
pcOptHashes :: PrettyCookedHashOpts,
    -- | Whether to display the log
    PrettyCookedOpts -> Bool
pcOptPrintLog :: Bool
  }
  deriving (PrettyCookedOpts -> PrettyCookedOpts -> Bool
(PrettyCookedOpts -> PrettyCookedOpts -> Bool)
-> (PrettyCookedOpts -> PrettyCookedOpts -> Bool)
-> Eq PrettyCookedOpts
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PrettyCookedOpts -> PrettyCookedOpts -> Bool
== :: PrettyCookedOpts -> PrettyCookedOpts -> Bool
$c/= :: PrettyCookedOpts -> PrettyCookedOpts -> Bool
/= :: PrettyCookedOpts -> PrettyCookedOpts -> Bool
Eq, Int -> PrettyCookedOpts -> ShowS
[PrettyCookedOpts] -> ShowS
PrettyCookedOpts -> String
(Int -> PrettyCookedOpts -> ShowS)
-> (PrettyCookedOpts -> String)
-> ([PrettyCookedOpts] -> ShowS)
-> Show PrettyCookedOpts
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PrettyCookedOpts -> ShowS
showsPrec :: Int -> PrettyCookedOpts -> ShowS
$cshow :: PrettyCookedOpts -> String
show :: PrettyCookedOpts -> String
$cshowList :: [PrettyCookedOpts] -> ShowS
showList :: [PrettyCookedOpts] -> ShowS
Show)

instance Default PrettyCookedOpts where
  def :: PrettyCookedOpts
def =
    PrettyCookedOpts
      { pcOptPrintTxHashes :: Bool
pcOptPrintTxHashes = Bool
False,
        pcOptPrintTxOutRefs :: PCOptTxOutRefs
pcOptPrintTxOutRefs = PCOptTxOutRefs
PCOptTxOutRefsHidden,
        pcOptPrintDefaultTxOpts :: Bool
pcOptPrintDefaultTxOpts = Bool
False,
        pcOptNumericUnderscores :: Bool
pcOptNumericUnderscores = Bool
True,
        pcOptHashes :: PrettyCookedHashOpts
pcOptHashes = PrettyCookedHashOpts
forall a. Default a => a
def,
        pcOptPrintLog :: Bool
pcOptPrintLog = Bool
True
      }

-- | Whether to print transaction outputs references.
data PCOptTxOutRefs
  = -- | Hide them
    PCOptTxOutRefsHidden
  | -- | Always show them.
    --
    -- Warning: this will disable printing similar UTxOs as a group (for
    -- instance @(×10) Lovelace: 100_000_000@)
    PCOptTxOutRefsFull
  | -- | Show them for UTxOs which are not grouped with similar others. This
    -- avoids the downside of 'PCOptTxOutRefsFull' which disables printing UTxOs
    -- as a group.
    PCOptTxOutRefsPartial
  deriving (PCOptTxOutRefs -> PCOptTxOutRefs -> Bool
(PCOptTxOutRefs -> PCOptTxOutRefs -> Bool)
-> (PCOptTxOutRefs -> PCOptTxOutRefs -> Bool) -> Eq PCOptTxOutRefs
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PCOptTxOutRefs -> PCOptTxOutRefs -> Bool
== :: PCOptTxOutRefs -> PCOptTxOutRefs -> Bool
$c/= :: PCOptTxOutRefs -> PCOptTxOutRefs -> Bool
/= :: PCOptTxOutRefs -> PCOptTxOutRefs -> Bool
Eq, Int -> PCOptTxOutRefs -> ShowS
[PCOptTxOutRefs] -> ShowS
PCOptTxOutRefs -> String
(Int -> PCOptTxOutRefs -> ShowS)
-> (PCOptTxOutRefs -> String)
-> ([PCOptTxOutRefs] -> ShowS)
-> Show PCOptTxOutRefs
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PCOptTxOutRefs -> ShowS
showsPrec :: Int -> PCOptTxOutRefs -> ShowS
$cshow :: PCOptTxOutRefs -> String
show :: PCOptTxOutRefs -> String
$cshowList :: [PCOptTxOutRefs] -> ShowS
showList :: [PCOptTxOutRefs] -> ShowS
Show)

data PrettyCookedHashOpts = PrettyCookedHashOpts
  { -- | Length of printed hash prefix. By default: 7
    PrettyCookedHashOpts -> Int
pcOptHashLength :: Int,
    -- | Association between hashes and given names to ease readability.  For
    -- example @Map.singleton (walletPKHash (wallet 1)) "Alice"@ By default:
    -- "defaultHashNames" which assigns Lovelace, Quick, and Permanent as names
    -- for the associated currency symbols
    PrettyCookedHashOpts -> Map BuiltinByteString String
pcOptHashNames :: Map Api.BuiltinByteString String,
    -- | When a given name exists for a hash, this flag also prints the original
    -- hash after the name. By default: @False@
    PrettyCookedHashOpts -> Bool
pcOptHashVerbose :: Bool
  }
  deriving (PrettyCookedHashOpts -> PrettyCookedHashOpts -> Bool
(PrettyCookedHashOpts -> PrettyCookedHashOpts -> Bool)
-> (PrettyCookedHashOpts -> PrettyCookedHashOpts -> Bool)
-> Eq PrettyCookedHashOpts
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PrettyCookedHashOpts -> PrettyCookedHashOpts -> Bool
== :: PrettyCookedHashOpts -> PrettyCookedHashOpts -> Bool
$c/= :: PrettyCookedHashOpts -> PrettyCookedHashOpts -> Bool
/= :: PrettyCookedHashOpts -> PrettyCookedHashOpts -> Bool
Eq, Int -> PrettyCookedHashOpts -> ShowS
[PrettyCookedHashOpts] -> ShowS
PrettyCookedHashOpts -> String
(Int -> PrettyCookedHashOpts -> ShowS)
-> (PrettyCookedHashOpts -> String)
-> ([PrettyCookedHashOpts] -> ShowS)
-> Show PrettyCookedHashOpts
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PrettyCookedHashOpts -> ShowS
showsPrec :: Int -> PrettyCookedHashOpts -> ShowS
$cshow :: PrettyCookedHashOpts -> String
show :: PrettyCookedHashOpts -> String
$cshowList :: [PrettyCookedHashOpts] -> ShowS
showList :: [PrettyCookedHashOpts] -> ShowS
Show)

instance Default PrettyCookedHashOpts where
  def :: PrettyCookedHashOpts
def =
    PrettyCookedHashOpts
      { pcOptHashLength :: Int
pcOptHashLength = Int
7,
        pcOptHashNames :: Map BuiltinByteString String
pcOptHashNames = Map BuiltinByteString String
defaultHashNames,
        pcOptHashVerbose :: Bool
pcOptHashVerbose = Bool
False
      }

-- | Default hash to names map that assigns Lovelace, Quick, and Permanent to
-- the associated currency symbols. This is used as the default for the
-- pretty-printing option and is recommended to use as a basis to extend with
-- custom names.
defaultHashNames :: Map Api.BuiltinByteString String
defaultHashNames :: Map BuiltinByteString String
defaultHashNames =
  [(CurrencySymbol, String)] -> Map BuiltinByteString String
forall a. ToHash a => [(a, String)] -> Map BuiltinByteString String
hashNamesFromList
    [ (BuiltinByteString -> CurrencySymbol
Api.CurrencySymbol BuiltinByteString
"", String
"Lovelace"),
      (CurrencySymbol
quickCurrencySymbol, String
"Quick"),
      (CurrencySymbol
permanentCurrencySymbol, String
"Permanent")
    ]
    Map BuiltinByteString String
-> Map BuiltinByteString String -> Map BuiltinByteString String
forall a. Semigroup a => a -> a -> a
<> [(Wallet, String)] -> Map BuiltinByteString String
forall a. ToHash a => [(a, String)] -> Map BuiltinByteString String
hashNamesFromList
      ((\Integer
i -> (Integer -> Wallet
wallet Integer
i, String
"wallet " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Integer -> String
forall a. Show a => a -> String
show Integer
i)) (Integer -> (Wallet, String)) -> [Integer] -> [(Wallet, String)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Integer
1 .. Integer
10])

-- | Smart constructor for maps to be used in the "pcOptHashNames"
-- pretty-printing option.
hashNamesFromList :: (ToHash a) => [(a, String)] -> Map Api.BuiltinByteString String
hashNamesFromList :: forall a. ToHash a => [(a, String)] -> Map BuiltinByteString String
hashNamesFromList = [(BuiltinByteString, String)] -> Map BuiltinByteString String
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(BuiltinByteString, String)] -> Map BuiltinByteString String)
-> ([(a, String)] -> [(BuiltinByteString, String)])
-> [(a, String)]
-> Map BuiltinByteString String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a, String) -> (BuiltinByteString, String))
-> [(a, String)] -> [(BuiltinByteString, String)]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> BuiltinByteString)
-> (a, String) -> (BuiltinByteString, String)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> BuiltinByteString
forall a. ToHash a => a -> BuiltinByteString
toHash)