/*
  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/post-management-wire.h
 * @brief C interface for POST /management/wire
 * @author Christian Grothoff
 */
#ifndef _TALER_EXCHANGE__POST_MANAGEMENT_WIRE_H
#define _TALER_EXCHANGE__POST_MANAGEMENT_WIRE_H

#include <taler/exchange/common.h>


/**
 * Possible options we can set for the POST /management/wire request.
 */
enum TALER_EXCHANGE_PostManagementWireOption
{
  /**
   * End of list of options.
   */
  TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_END = 0,

  /**
   * Label to use when showing the account to users.
   * If not set, no label is used.
   */
  TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_BANK_LABEL,

  /**
   * Priority for ordering the bank accounts when displaying to users.
   * If not set, defaults to 0.
   */
  TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_PRIORITY,

  /**
   * URL of conversion service to use.
   * If not set, no conversion is used.
   */
  TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CONVERSION_URL,

  /**
   * Open banking gateway that could be used.
   * If not set, no open banking gateway is available.
   */
  TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_OPEN_BANKING_GATEWAY,

  /**
   * Prepared transfer service URL for short wire transfer subjects.
   * If not set, no wire transfer gateway is used.
   */
  TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_PREPARED_TRANSFER_URL,

  /**
   * Set of credit restrictions to apply.
   * If not set, no credit restrictions apply.
   */
  TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CREDIT_RESTRICTIONS,

  /**
   * Set of debit restrictions to apply.
   * If not set, no debit restrictions apply.
   */
  TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_DEBIT_RESTRICTIONS

};


/**
 * Value for an option we can set for the POST /management/wire request.
 */
struct TALER_EXCHANGE_PostManagementWireOptionValue
{
  /**
   * Type of the option being set.
   */
  enum TALER_EXCHANGE_PostManagementWireOption option;

  /**
   * Specific option value.
   */
  union
  {
    /**
     * Value if @e option is
     * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_BANK_LABEL.
     * May be NULL.
     */
    const char *bank_label;

    /**
     * Value if @e option is
     * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CONVERSION_URL.
     * May be NULL.
     */
    const char *conversion_url;

    /**
     * Value if @e option is
     * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_OPEN_BANKING_GATEWAY.
     * May be NULL.
     */
    const char *open_banking_gateway;

    /**
     * Value if @e option is
     * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_PREPARED_TRANSFER_SERVICE.
     * May be NULL.
     */
    const char *prepared_transfer_url;

    /**
     * Value if @e option is
     * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CREDIT_RESTRICTIONS.
     * May be NULL.
     */
    const json_t *credit_restrictions;

    /**
     * Value if @e option is
     * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_DEBIT_RESTRICTIONS.
     * May be NULL.
     */
    const json_t *debit_restrictions;

    /**
     * Value if @e option is
     * #TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_PRIORITY.
     */
    int64_t priority;

  } details;

};


/**
 * Handle for an operation to POST /management/wire.
 */
struct TALER_EXCHANGE_PostManagementWireHandle;


/**
 * Set up POST /management/wire operation.
 * Note that you must explicitly start the operation after setup.
 *
 * @param ctx the context
 * @param url HTTP base URL for the exchange
 * @param payto_uri RFC 8905 URI of the exchange's bank account
 * @param validity_start when was this decided?
 * @param master_sig1 signature affirming the wire addition
 *        of purpose #TALER_SIGNATURE_MASTER_ADD_WIRE
 * @param master_sig2 signature affirming the validity of the account for clients;
 *        of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS
 * @return handle to operation, NULL on error
 */
struct TALER_EXCHANGE_PostManagementWireHandle *
TALER_EXCHANGE_post_management_wire_create (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  const struct TALER_FullPayto payto_uri,
  struct GNUNET_TIME_Timestamp validity_start,
  const struct TALER_MasterSignatureP *master_sig1,
  const struct TALER_MasterSignatureP *master_sig2);


/**
 * Terminate the list of options.
 *
 * @return the terminating object of struct TALER_EXCHANGE_PostManagementWireOptionValue
 */
#define TALER_EXCHANGE_post_management_wire_option_end_()              \
        (const struct TALER_EXCHANGE_PostManagementWireOptionValue)    \
        {                                                              \
          .option = TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_END    \
        }

/**
 * Set the bank label for the wire account.
 *
 * @param l the label string, or NULL for no label
 * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue
 */
#define TALER_EXCHANGE_post_management_wire_option_bank_label(l)             \
        (const struct TALER_EXCHANGE_PostManagementWireOptionValue)           \
        {                                                                     \
          .option = TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_BANK_LABEL,   \
          .details.bank_label = (l)                                           \
        }


/**
 * Set the priority for ordering the bank accounts.
 *
 * @param p priority value (higher is shown first)
 * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue
 */
#define TALER_EXCHANGE_post_management_wire_option_priority(p)               \
        (const struct TALER_EXCHANGE_PostManagementWireOptionValue)           \
        {                                                                     \
          .option = TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_PRIORITY,     \
          .details.priority = (p)                                             \
        }


/**
 * Set the conversion URL for the wire account.
 *
 * @param u the conversion service URL string, or NULL for no conversion
 * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue
 */
#define TALER_EXCHANGE_post_management_wire_option_conversion_url(u)              \
        (const struct TALER_EXCHANGE_PostManagementWireOptionValue)               \
        {                                                                         \
          .option = TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CONVERSION_URL,   \
          .details.conversion_url = (u)                                           \
        }


/**
 * Set the open banking gateway for the wire account.
 *
 * @param g the open banking gateway URL string, or NULL for no gateway
 * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue
 */
#define TALER_EXCHANGE_post_management_wire_option_open_banking_gateway(g)              \
        (const struct TALER_EXCHANGE_PostManagementWireOptionValue)                     \
        {                                                                               \
          .option = \
            TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_OPEN_BANKING_GATEWAY,   \
          .details.open_banking_gateway = (g)                                           \
        }


/**
 * Set the wire transfer gateway for the wire account.
 *
 * @param g the wire transfer gateway URL string, or NULL for no gateway
 * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue
 */
#define TALER_EXCHANGE_post_management_wire_option_prepared_transfer_url(g)              \
        (const struct TALER_EXCHANGE_PostManagementWireOptionValue)                      \
        {                                                                                \
          .option = \
            TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_PREPARED_TRANSFER_URL,   \
          .details.prepared_transfer_url = (g)                                           \
        }


/**
 * Set the credit restrictions for the wire account.
 *
 * @param r JSON encoding of the credit restrictions, or NULL for no restrictions
 * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue
 */
#define TALER_EXCHANGE_post_management_wire_option_credit_restrictions(r)              \
        (const struct TALER_EXCHANGE_PostManagementWireOptionValue)                    \
        {                                                                              \
          .option = \
            TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_CREDIT_RESTRICTIONS,   \
          .details.credit_restrictions = (r)                                           \
        }


/**
 * Set the debit restrictions for the wire account.
 *
 * @param r JSON encoding of the debit restrictions, or NULL for no restrictions
 * @return representation of the option as a struct TALER_EXCHANGE_PostManagementWireOptionValue
 */
#define TALER_EXCHANGE_post_management_wire_option_debit_restrictions(r)              \
        (const struct TALER_EXCHANGE_PostManagementWireOptionValue)                   \
        {                                                                             \
          .option = \
            TALER_EXCHANGE_POST_MANAGEMENT_WIRE_OPTION_DEBIT_RESTRICTIONS,   \
          .details.debit_restrictions = (r)                                           \
        }

/**
 * Set the requested options for the operation.
 *
 * If any option fails, other options may or may not be applied.
 *
 * @param pmwh the request to set the options for
 * @param num_options length of the @a options array
 * @param options an array of options of length @a num_array,
 *        or alternatively terminated by
 *        TALER_EXCHANGE_post_management_wire_option_end_()
 * @return #GNUNET_OK on success,
 *         #GNUNET_NO on failure,
 *         #GNUNET_SYSERR on internal error
 */
enum GNUNET_GenericReturnValue
TALER_EXCHANGE_post_management_wire_set_options_ (
  struct TALER_EXCHANGE_PostManagementWireHandle *pmwh,
  unsigned int num_options,
  const struct TALER_EXCHANGE_PostManagementWireOptionValue options[]);


/**
 * Set the requested options for the operation.
 *
 * If any option fails, other options may or may not be applied.
 *
 * @param pmwh the request to set the options for
 * @param ... the list of the options, each option must be created
 *            by helpers TALER_EXCHANGE_post_management_wire_option_NAME(VALUE)
 * @return #GNUNET_OK on success,
 *         #GNUNET_NO on failure,
 *         #GNUNET_SYSERR on internal error
 */
#define TALER_EXCHANGE_post_management_wire_set_options(pmwh,...)          \
        TALER_EXCHANGE_post_management_wire_set_options_ (                 \
          pmwh,                                                            \
          TALER_EXCHANGE_COMMON_OPTIONS_ARRAY_MAX_SIZE,                    \
          ((const struct TALER_EXCHANGE_PostManagementWireOptionValue[])   \
           {__VA_ARGS__,                                                   \
            TALER_EXCHANGE_post_management_wire_option_end_ ()}            \
          ))


/**
 * Response from a POST /management/wire request.
 */
struct TALER_EXCHANGE_PostManagementWireResponse
{
  /**
   * HTTP response data.
   */
  struct TALER_EXCHANGE_HttpResponse hr;
};


#ifndef TALER_EXCHANGE_POST_MANAGEMENT_WIRE_RESULT_CLOSURE
/**
 * Type of the closure used by
 * the #TALER_EXCHANGE_PostManagementWireCallback.
 */
#define TALER_EXCHANGE_POST_MANAGEMENT_WIRE_RESULT_CLOSURE void
#endif /* TALER_EXCHANGE_POST_MANAGEMENT_WIRE_RESULT_CLOSURE */

/**
 * Type of the function that receives the result of a
 * POST /management/wire request.
 *
 * @param cls closure
 * @param result result returned by the HTTP server
 */
typedef void
(*TALER_EXCHANGE_PostManagementWireCallback)(
  TALER_EXCHANGE_POST_MANAGEMENT_WIRE_RESULT_CLOSURE *cls,
  const struct TALER_EXCHANGE_PostManagementWireResponse *result);


/**
 * Start POST /management/wire operation.
 *
 * @param[in,out] pmwh 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_post_management_wire_start (
  struct TALER_EXCHANGE_PostManagementWireHandle *pmwh,
  TALER_EXCHANGE_PostManagementWireCallback cb,
  TALER_EXCHANGE_POST_MANAGEMENT_WIRE_RESULT_CLOSURE *cb_cls);


/**
 * Cancel POST /management/wire operation.  This function must not be called
 * by clients after the TALER_EXCHANGE_PostManagementWireCallback has been
 * invoked (as in those cases it'll be called internally by the implementation
 * already).
 *
 * @param[in] pmwh operation to cancel
 */
void
TALER_EXCHANGE_post_management_wire_cancel (
  struct TALER_EXCHANGE_PostManagementWireHandle *pmwh);


#endif /* _TALER_EXCHANGE__POST_MANAGEMENT_WIRE_H */
