{-# LANGUAGE DataKinds     #-}
{-# LANGUAGE TypeOperators #-}

module Cardano.Wallet.Mock.API
    ( API
    ) where

import Cardano.Wallet.Mock.Types (WalletInfo)
import Data.List.NonEmpty (NonEmpty)
import Ledger (CardanoAddress, PaymentPubKeyHash)
import Ledger.Tx (CardanoTx)
import Ledger.Tx.Constraints.OffChain (UnbalancedTx)
import Plutus.V1.Ledger.Api (Value)
import Servant.API (Capture, Get, JSON, NoContent, Post, QueryParam, ReqBody, (:<|>), (:>))
import Wallet.Emulator.Error (WalletAPIError)

{- Note [WalletID type in wallet API]

We use the following type to identify wallets:

@newtype Wallet = Wallet Integer@

This creates two problems for the purescript bridge:

1. We need to use a bigint library in Purescript. This is done in
'PSGenerator.Common.integerBridge'. Technically, JSON numbers have no size
limit, but we need the special library for parsing (I think!)
2. Sometimes we want to use 'Wallet' as part of a URL. Normally we would do
this in servant with 'Capture "walletId" Wallet'. But this is going to break
the purescript bridge that generates the API client, because it can't handle
'Wallet' or even 'Integer' types.
To address this, we parameterise the API over the type of wallet ID. In the
servant server implementation we specialise this to 'Integer'. In the
PSGenerator we specialise it to 'Text'.

-}

type API walletId -- see note [WalletID type in wallet API]
    = "create" :> QueryParam "funds" Integer :> Post '[JSON] WalletInfo
      :<|> Capture "walletId" walletId :> "submit-txn" :> ReqBody '[JSON] CardanoTx :> Post '[JSON] NoContent
      -- TODO: Should we removed in favor of 'own-addresses'. However, how do we deprecate an HTTP request?
      :<|> Capture "walletId" walletId :> "own-payment-public-key-hash" :> Get '[JSON] PaymentPubKeyHash
      :<|> Capture "walletId" walletId :> "own-addresses" :> Get '[JSON] (NonEmpty CardanoAddress)
      :<|> Capture "walletId" walletId :> "balance-tx" :> ReqBody '[JSON] UnbalancedTx :> Post '[JSON] (Either WalletAPIError CardanoTx)
      -- TODO: Should we removed as deprecated
      :<|> Capture "walletId" walletId :> "total-funds" :> Get '[JSON] Value
      :<|> Capture "walletId" walletId :> "sign" :> ReqBody '[JSON] CardanoTx :> Post '[JSON] CardanoTx