-- | Lovelaces

{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE UndecidableInstances #-}

module Blockfrost.Types.Shared.Ada
  ( Lovelaces
  ) where

import Data.Aeson (Encoding, FromJSON (..), ToJSON (..), Value)
import Data.Proxy (Proxy (..))
import Data.Text (Text)
import GHC.TypeLits (KnownSymbol)
import qualified Money
import Servant.Docs (ToSample (..), samples)

type Lovelaces = Money.Discrete "ADA" "lovelace"

instance (KnownSymbol cur, Money.GoodScale sc) => ToSample (Money.Discrete' cur sc) where
  toSamples :: Proxy (Discrete' cur sc) -> [(Text, Discrete' cur sc)]
toSamples Proxy (Discrete' cur sc)
_ = [Discrete' cur sc] -> [(Text, Discrete' cur sc)]
forall a. [a] -> [(Text, a)]
samples ([Discrete' cur sc] -> [(Text, Discrete' cur sc)])
-> [Discrete' cur sc] -> [(Text, Discrete' cur sc)]
forall a b. (a -> b) -> a -> b
$ (Integer -> Discrete' cur sc) -> [Integer] -> [Discrete' cur sc]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> Discrete' cur sc
forall (scale :: (Nat, Nat)) (currency :: Symbol).
GoodScale scale =>
Integer -> Discrete' currency scale
Money.discrete [
      Integer
592661
    , Integer
3592661
    , Integer
1337
    , Integer
42
    , Integer
0
    , Integer
3000100
    ]

lovelaceDecimalConfig :: Money.DecimalConf
lovelaceDecimalConfig :: DecimalConf
lovelaceDecimalConfig =
  DecimalConf
Money.defaultDecimalConf
    { decimalConf_digits :: Word8
Money.decimalConf_digits = Word8
0
    , decimalConf_scale :: Scale
Money.decimalConf_scale =
        Proxy '(1000000, 1) -> Scale
forall (proxy :: (Nat, Nat) -> *) (scale :: (Nat, Nat)).
GoodScale scale =>
proxy scale -> Scale
Money.scale (Proxy (UnitScale "ADA" "lovelace")
forall k (t :: k). Proxy t
Proxy @(Money.UnitScale "ADA" "lovelace"))
    }

instance ToJSON (Money.Discrete' "ADA" '(1_000_000, 1)) where
  toJSON :: Discrete' "ADA" '(1000000, 1) -> Value
toJSON =
      (Text -> Value
forall a. ToJSON a => a -> Value
toJSON :: Text -> Value)
    (Text -> Value)
-> (Discrete' "ADA" '(1000000, 1) -> Text)
-> Discrete' "ADA" '(1000000, 1)
-> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DecimalConf
-> Approximation -> Discrete' "ADA" '(1000000, 1) -> Text
forall (scale :: (Nat, Nat)) (currency :: Symbol).
GoodScale scale =>
DecimalConf -> Approximation -> Discrete' currency scale -> Text
Money.discreteToDecimal
        DecimalConf
lovelaceDecimalConfig
        Approximation
Money.Round
  toEncoding :: Discrete' "ADA" '(1000000, 1) -> Encoding
toEncoding =
      (Text -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding :: Text -> Encoding)
    (Text -> Encoding)
-> (Discrete' "ADA" '(1000000, 1) -> Text)
-> Discrete' "ADA" '(1000000, 1)
-> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DecimalConf
-> Approximation -> Discrete' "ADA" '(1000000, 1) -> Text
forall (scale :: (Nat, Nat)) (currency :: Symbol).
GoodScale scale =>
DecimalConf -> Approximation -> Discrete' currency scale -> Text
Money.discreteToDecimal
        DecimalConf
lovelaceDecimalConfig
        Approximation
Money.Round

instance FromJSON (Money.Discrete' "ADA" '(1000000, 1)) where
  parseJSON :: Value -> Parser (Discrete' "ADA" '(1000000, 1))
parseJSON Value
v = do
     Text
t <- Value -> Parser Text
forall a. FromJSON a => Value -> Parser a
parseJSON Value
v
     Parser (Discrete' "ADA" '(1000000, 1))
-> (Discrete' "ADA" '(1000000, 1)
    -> Parser (Discrete' "ADA" '(1000000, 1)))
-> Maybe (Discrete' "ADA" '(1000000, 1))
-> Parser (Discrete' "ADA" '(1000000, 1))
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
        (String -> Parser (Discrete' "ADA" '(1000000, 1))
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Can't parse Discrete ADA value")
        Discrete' "ADA" '(1000000, 1)
-> Parser (Discrete' "ADA" '(1000000, 1))
forall (f :: * -> *) a. Applicative f => a -> f a
pure
        (DecimalConf -> Text -> Maybe (Discrete' "ADA" '(1000000, 1))
forall (scale :: (Nat, Nat)) (currency :: Symbol).
GoodScale scale =>
DecimalConf -> Text -> Maybe (Discrete' currency scale)
Money.discreteFromDecimal DecimalConf
lovelaceDecimalConfig Text
t)