/*
  This file is part of TALER
  Copyright (C) 2014-2026 Taler Systems SA

  TALER is free software; you can redistribute it and/or modify it under the
  terms of the GNU Affero General Public License as published by the Free Software
  Foundation; either version 3, or (at your option) any later version.

  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License along with
  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */
/**
 * @file include/taler/exchange/get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.h
 * @brief C interface for GET /deposits/$H_WIRE/$MERCHANT_PUB/$H_CONTRACT_TERMS/$COIN_PUB
 * @author Christian Grothoff
 */
#ifndef \
  _TALER_EXCHANGE__GET_DEPOSITS_H_WIRE_MERCHANT_PUB_H_CONTRACT_TERMS_COIN_PUB_H
#define \
        _TALER_EXCHANGE__GET_DEPOSITS_H_WIRE_MERCHANT_PUB_H_CONTRACT_TERMS_COIN_PUB_H

#include <taler/exchange/common.h>

/**
 * Possible options we can set for the GET deposits request.
 */
enum TALER_EXCHANGE_GetDepositsOption
{
  /**
   * End of list of options.
   */
  TALER_EXCHANGE_GET_DEPOSITS_OPTION_END = 0,

  /**
   * How long to wait for the wire transfer to be executed,
   * enabling long polling.  Default is zero (no long polling).
   */
  TALER_EXCHANGE_GET_DEPOSITS_OPTION_TIMEOUT,

  /**
   * Set the long-poll target type.  Default is #TALER_DGLPT_OK.
   * Use #TALER_DGLPT_KYC_REQUIRED_OR_OK to also wake up when
   * the KYC status changes.
   */
  TALER_EXCHANGE_GET_DEPOSITS_OPTION_LONG_POLL_TARGET

};


/**
 * Value for an option for the GET deposits request.
 */
struct TALER_EXCHANGE_GetDepositsOptionValue
{
  /**
   * Type of the option being set.
   */
  enum TALER_EXCHANGE_GetDepositsOption option;

  /**
   * Specific option value.
   */
  union
  {
    /**
     * Value if @e option is TALER_EXCHANGE_GET_DEPOSITS_OPTION_TIMEOUT.
     */
    struct GNUNET_TIME_Relative timeout;

    /**
     * Value if @e option is
     * #TALER_EXCHANGE_GET_DEPOSITS_OPTION_LONG_POLL_TARGET.
     */
    enum TALER_DepositGetLongPollTarget lpt;

  } details;

};


/**
 * Handle for an operation to GET /deposits/$H_WIRE/$MERCHANT_PUB/$H_CONTRACT_TERMS/$COIN_PUB.
 */
struct TALER_EXCHANGE_GetDepositsHandle;


/**
 * Set up GET /deposits/... operation.
 * Note that you must explicitly start the operation after
 * possibly setting options.
 *
 * @param ctx the context
 * @param url base URL of the exchange
 * @param keys exchange keys for signature verification
 * @param merchant_priv private key of the merchant
 * @param h_wire hash of the merchant's wire transfer details
 * @param h_contract_terms hash of the proposal data
 * @param coin_pub public key of the coin
 * @return handle to operation
 */
struct TALER_EXCHANGE_GetDepositsHandle *
TALER_EXCHANGE_get_deposits_create (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  struct TALER_EXCHANGE_Keys *keys,
  const struct TALER_MerchantPrivateKeyP *merchant_priv,
  const struct TALER_MerchantWireHashP *h_wire,
  const struct TALER_PrivateContractHashP *h_contract_terms,
  const struct TALER_CoinSpendPublicKeyP *coin_pub);


/**
 * Terminate the list of options.
 *
 * @return the terminating object of struct TALER_EXCHANGE_GetDepositsOptionValue
 */
#define TALER_EXCHANGE_get_deposits_option_end_()                   \
        (const struct TALER_EXCHANGE_GetDepositsOptionValue)        \
        {                                                            \
          .option = TALER_EXCHANGE_GET_DEPOSITS_OPTION_END          \
        }

/**
 * Set long-polling timeout.
 *
 * @param t how long to wait for the wire transfer to be executed
 * @return representation of the option as a struct TALER_EXCHANGE_GetDepositsOptionValue
 */
#define TALER_EXCHANGE_get_deposits_option_timeout(t)                   \
        (const struct TALER_EXCHANGE_GetDepositsOptionValue)            \
        {                                                                \
          .option = TALER_EXCHANGE_GET_DEPOSITS_OPTION_TIMEOUT,         \
          .details.timeout = (t)                                         \
        }

/**
 * Set the long-poll target type.
 *
 * @param target a #TALER_DepositGetLongPollTarget value
 * @return representation of the option as a struct TALER_EXCHANGE_GetDepositsOptionValue
 */
#define TALER_EXCHANGE_get_deposits_option_long_poll_target(target)     \
        (const struct TALER_EXCHANGE_GetDepositsOptionValue)            \
        {                                                                \
          .option =                                                      \
            TALER_EXCHANGE_GET_DEPOSITS_OPTION_LONG_POLL_TARGET,        \
          .details.lpt = (target)                                        \
        }


/**
 * Set the requested options for the operation.
 *
 * If any option fails, other options may or may not be applied.
 *
 * @param gdh the request to set the options for
 * @param num_options length of the @a options array
 * @param options an array of options
 * @return #GNUNET_OK on success,
 *         #GNUNET_NO on failure,
 *         #GNUNET_SYSERR on internal error
 */
enum GNUNET_GenericReturnValue
TALER_EXCHANGE_get_deposits_set_options_ (
  struct TALER_EXCHANGE_GetDepositsHandle *gdh,
  unsigned int num_options,
  const struct TALER_EXCHANGE_GetDepositsOptionValue *options);


/**
 * Set the requested options for the operation.
 *
 * If any option fails, other options may or may not be applied.
 *
 * It should be used with helpers that create required options, for example:
 *
 * TALER_EXCHANGE_get_deposits_set_options (
 *   gdh,
 *   TALER_EXCHANGE_get_deposits_option_timeout (timeout));
 *
 * @param gdh the request to set the options for
 * @param ... the list of options, each created by a
 *            TALER_EXCHANGE_get_deposits_option_NAME(VALUE) helper
 * @return #GNUNET_OK on success,
 *         #GNUNET_NO on failure,
 *         #GNUNET_SYSERR on internal error
 */
#define TALER_EXCHANGE_get_deposits_set_options(gdh,...)              \
        TALER_EXCHANGE_get_deposits_set_options_ (                    \
          gdh,                                                         \
          TALER_EXCHANGE_COMMON_OPTIONS_ARRAY_MAX_SIZE,               \
          ((const struct TALER_EXCHANGE_GetDepositsOptionValue[])     \
           {__VA_ARGS__, TALER_EXCHANGE_get_deposits_option_end_ () } \
          ))


/**
 * Data returned for a successfully executed wire transfer (HTTP 200 OK).
 */
struct TALER_EXCHANGE_DepositData
{
  /**
   * Exchange key used to sign.
   */
  struct TALER_ExchangePublicKeyP exchange_pub;

  /**
   * Signature from the exchange over the deposit data.
   */
  struct TALER_ExchangeSignatureP exchange_sig;

  /**
   * Wire transfer identifier used by the exchange.
   */
  struct TALER_WireTransferIdentifierRawP wtid;

  /**
   * Actual execution time for the wire transfer.
   */
  struct GNUNET_TIME_Timestamp execution_time;

  /**
   * This coin's contribution to the total wire transfer amount.
   */
  struct TALER_Amount coin_contribution;

};


/**
 * Data returned for a successful GET /deposits/... request.
 */
struct TALER_EXCHANGE_GetDepositsResponse
{
  /**
   * HTTP response data.
   */
  struct TALER_EXCHANGE_HttpResponse hr;

  /**
   * Details about the response.
   */
  union
  {
    /**
     * Response if the status was #MHD_HTTP_OK.
     * The wire transfer has been executed.
     */
    struct TALER_EXCHANGE_DepositData ok;

    /**
     * Response if the status was #MHD_HTTP_ACCEPTED.
     * The wire transfer has not yet been executed.
     */
    struct
    {
      /**
       * Planned execution time for the wire transfer.
       */
      struct GNUNET_TIME_Timestamp execution_time;

      /**
       * Public key needed to access the KYC state of this account.
       * All zeros if a wire transfer is required first to establish the key.
       */
      union TALER_AccountPublicKeyP account_pub;

      /**
       * KYC legitimization requirement that the merchant should use to check
       * for its KYC status.
       * @deprecated, no longer needed.
       */
      uint64_t requirement_row;

      /**
       * True if the KYC check is already finished and the exchange is
       * merely waiting for the @e execution_time.
       */
      bool kyc_ok;

    } accepted;

  } details;

};


#ifndef TALER_EXCHANGE_GET_DEPOSITS_RESULT_CLOSURE
/**
 * Type of the closure used by
 * the #TALER_EXCHANGE_GetDepositsCallback.
 */
#define TALER_EXCHANGE_GET_DEPOSITS_RESULT_CLOSURE void
#endif /* TALER_EXCHANGE_GET_DEPOSITS_RESULT_CLOSURE */

/**
 * Type of the function that receives the result of a
 * GET /deposits/... request.
 *
 * @param cls closure
 * @param result result returned by the HTTP server
 */
typedef void
(*TALER_EXCHANGE_GetDepositsCallback)(
  TALER_EXCHANGE_GET_DEPOSITS_RESULT_CLOSURE *cls,
  const struct TALER_EXCHANGE_GetDepositsResponse *result);


/**
 * Start GET /deposits/... operation.
 *
 * @param[in,out] gdh operation to start
 * @param cb function to call with the exchange's result
 * @param cb_cls closure for @a cb
 * @return status code, #TALER_EC_NONE on success
 */
enum TALER_ErrorCode
TALER_EXCHANGE_get_deposits_start (
  struct TALER_EXCHANGE_GetDepositsHandle *gdh,
  TALER_EXCHANGE_GetDepositsCallback cb,
  TALER_EXCHANGE_GET_DEPOSITS_RESULT_CLOSURE *cb_cls);


/**
 * Cancel GET /deposits/... operation.  This function must not be called
 * by clients after the TALER_EXCHANGE_GetDepositsCallback has been invoked
 * (as in those cases it'll be called internally by the
 * implementation already).
 *
 * @param[in] gdh operation to cancel
 */
void
TALER_EXCHANGE_get_deposits_cancel (
  struct TALER_EXCHANGE_GetDepositsHandle *gdh);


#endif /* \
  _TALER_EXCHANGE__GET_DEPOSITS_H_WIRE_MERCHANT_PUB_H_CONTRACT_TERMS_COIN_PUB_H */
