/*
   This file is part of TALER
   Copyright (C) 2023 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/donau_service.h
 * @brief C interface of libdonau, a C library to use donau's HTTP API
 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
 * @author Christian Grothoff
 * @author Özgür Kesim
 * @author Lukas Matyja
 */
#ifndef _DONAU_SERVICE_H
#define _DONAU_SERVICE_H

#include <jansson.h>
#include <taler/taler_util.h>
#include "donau_util.h"
#include <taler/taler_error_codes.h>
#include <gnunet/gnunet_curl_lib.h>


/* *********************  /keys *********************** */


/**
 * @brief Donau's statement signing public key
 */
struct DONAU_SigningPublicKeyAndValidity
{
  /**
   * The signing public key
   */
  struct DONAU_DonauPublicKeyP key;

  /**
   * Start time of the validity period for this key.
   */
  struct GNUNET_TIME_Timestamp valid_from;

  /**
   * The donau will sign messages with this key between @e start and this time.
   */
  struct GNUNET_TIME_Timestamp expire_sign;

};

/**
 * @brief Public information about a donau's donation unit signing key
 */
struct DONAU_DonationUnitInformation
{
  /**
   * The public key
   */
  struct DONAU_DonationUnitPublicKey key;

  /**
   * amount of the donation
   */
  struct TALER_Amount value;

  /**
   * Year of validity
   */
  uint64_t year;

  /**
   * Set to true if the private donation unit key has been
   * lost by the donau and thus the key cannot be
   * used for issuing receipts at this time.
   */
  bool lost;
};


/**
 * @brief Information about keys from the donau.
 */
struct DONAU_Keys
{

  /**
   * Array of the donau's online signing keys.
   */
  struct DONAU_SigningPublicKeyAndValidity *sign_keys;

  /**
   * Array of the donau's donation unit keys.
   */
  struct DONAU_DonationUnitInformation *donation_unit_keys;

  /**
   * Supported protocol version by the donau.
   * String in the format current:revision:age using the
   * semantics of GNU libtool.  See
   * https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
   */
  char *version;

  /**
   * Financial domain.
   */
  char *domain;

  /**
   * Supported currency of the donau.
   */
  char *currency;

  /**
   * What is the base URL of the donau that returned
   * these keys?
   */
  char *donau_url;

  /**
   * Specifies how an amount's fractional digits should be rendered.
   * More details in DD51.
   */
  struct TALER_CurrencySpecification currency_specification;

  /**
   * Length of the @e sign_keys array (number of valid entries).
   */
  unsigned int num_sign_keys;

  /**
   * Length of the @e donation_unit_keys array.
   */
  unsigned int num_donation_unit_keys;

  /**
 * Actual length of the @e donation_unit_keys array (size of allocation).
 */
  unsigned int donation_unit_keys_size;

  /**
   * Reference counter for this structure.
   * Freed when it reaches 0.
   */
  unsigned int rc;

};


/**
 * How compatible are the protocol version of the donau and this
 * client?  The bits (1,2,4) can be used to test if the donau's
 * version is incompatible, older or newer respectively.
 */
enum DONAU_VersionCompatibility
{

  /**
   * The donau runs exactly the same protocol version.
   */
  DONAU_VC_MATCH = 0,

  /**
   * The donau is too old or too new to be compatible with this
   * implementation (bit)
   */
  DONAU_VC_INCOMPATIBLE = 1,

  /**
   * The donau is older than this implementation (bit)
   */
  DONAU_VC_OLDER = 2,

  /**
   * The donau is too old to be compatible with
   * this implementation.
   */
  DONAU_VC_INCOMPATIBLE_OUTDATED
    = DONAU_VC_INCOMPATIBLE
      | DONAU_VC_OLDER,

  /**
   * The donau is more recent than this implementation (bit).
   */
  DONAU_VC_NEWER = 4,

  /**
   * The donau is too recent for this implementation.
   */
  DONAU_VC_INCOMPATIBLE_NEWER
    = DONAU_VC_INCOMPATIBLE
      | DONAU_VC_NEWER,

  /**
   * We could not even parse the version data.
   */
  DONAU_VC_PROTOCOL_ERROR = 8

};


/**
 * General information about the HTTP response we obtained
 * from the donau for a request.
 */
struct DONAU_HttpResponse
{

  /**
   * The complete JSON reply. NULL if we failed to parse the
   * reply (too big, invalid JSON).
   */
  const json_t *reply;

  /**
   * Set to the human-readable 'hint' that is optionally
   * provided by the donau together with errors. NULL
   * if no hint was provided or if there was no error.
   */
  const char *hint;

  /**
   * HTTP status code for the response.  0 if the
   * HTTP request failed and we did not get any answer, or
   * if the answer was invalid and we set @a ec to a
   * client-side error code.
   */
  unsigned int http_status;

  /**
   * Taler error code.  #TALER_EC_NONE if everything was
   * OK.  Usually set to the "code" field of an error
   * response, but may be set to values created at the
   * client side, for example when the response was
   * not in JSON format or was otherwise ill-formed.
   */
  enum TALER_ErrorCode ec;

};


/**
 * Response from /keys.
 */
struct DONAU_KeysResponse
{
  /**
   * HTTP response dataclosure
   */
  struct DONAU_HttpResponse hr;

  /**
   * Details depending on the HTTP status code.
   */
  union
  {

    /**
     * Details on #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * Information about the various keys used by the donau.
       */
      const struct DONAU_Keys *keys;

      /**
       * Protocol compatibility information
       */
      enum DONAU_VersionCompatibility compat;
    } ok;
  } details;

};


/**
 * Function called with information about
 * a particular donau and what keys the donau is using.
 * The ownership over the @a keys object is passed to
 * the callee, thus it is given explicitly and not
 * (only) via @a kr.
 *
 * @param cls closure
 * @param kr response from /keys
 * @param[in] keys keys object passed to callback with
 *  reference counter of 1. Must be freed by callee
 *  using #DONAU_keys_decref(). NULL on failure.
 */
typedef void
(*DONAU_GetKeysCallback) (
  void *cls,
  const struct DONAU_KeysResponse *kr,
  struct DONAU_Keys *keys);


/**
 * @brief Handle for a GET /keys request.
 */
struct DONAU_GetKeysHandle;


/**
 * Fetch the main /keys resources from an donau.  Does an incremental
 * fetch if @a last_keys is given. The obtained information will be passed to
 * the @a cert_cb (possibly after first merging it with @a last_keys to
 * produce a full picture; expired keys will be removed from @a
 * last_keys if there are any).
 *
 * @param ctx the context
 * @param url HTTP base URL for the donau
 * @param cert_cb function to call with the donau's certification information,
 *                possibly called repeatedly if the information changes
 * @param cert_cb_cls closure for @a cert_cb
 * @return the donau handle; NULL upon error
 */
struct DONAU_GetKeysHandle *
DONAU_get_keys (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  DONAU_GetKeysCallback cert_cb,
  void *cert_cb_cls);


/**
 * Serialize the latest data from @a keys to be persisted
 * (for example, to be used as @a last_keys later).
 *
 * @param kd the key data to serialize
 * @return NULL on error; otherwise JSON object owned by the caller
 */
json_t *
DONAU_keys_to_json (const struct DONAU_Keys *kd);


/**
 * Deserialize keys data stored in @a j.
 *
 * @param j JSON keys data previously returned from #DONAU_keys_to_json()
 * @return NULL on error (i.e. invalid JSON); otherwise
 *         keys object with reference counter 1 owned by the caller
 */
struct DONAU_Keys *
DONAU_keys_from_json (const json_t *j);


/**
 * Cancel GET /keys operation.
 *
 * @param[in] gkh the GET /keys handle
 */
void
DONAU_get_keys_cancel (struct DONAU_GetKeysHandle *gkh);


/**
 * Increment reference counter for @a keys
 *
 * @param[in,out] keys object to increment reference counter for
 * @return keys, with incremented reference counter
 */
struct DONAU_Keys *
DONAU_keys_incref (struct DONAU_Keys *keys);


/**
 * Decrement reference counter for @a keys.
 * Frees @a keys if reference counter becomes zero.
 *
 * @param[in,out] keys object to decrement reference counter for
 */
void
DONAU_keys_decref (struct DONAU_Keys *keys);

/**
 * Test if the given @a pub is a current signing key from the donau
 * according to @a keys. (->  // always current, revocation not yet supported)
 *
 * @param keys the donau's key set
 * @param pub claimed online signing key for the donau
 * @param year given year
 * @return #GNUNET_OK if @a pub is (according to /keys and @a year) the corresponding signing key
 */
// enum GNUNET_GenericReturnValue
// DONAU_test_signing_key (
//   const struct DONAU_Keys *keys,
//   const uint32_t year,
//   const struct DONAU_DonauPublicKeyP *pub);


/**
 * Obtain the donation unit key details from the donau.
 *
 * @param keys the donau's key set
 * @param pk public key of the donation unit to lookup
 * @return details about the given donation unit key, NULL if the key is not
 * found
 */
const struct DONAU_DonationUnitInformation *
DONAU_get_donation_unit_key (
  const struct DONAU_Keys *keys,
  const struct DONAU_DonationUnitPublicKey *pk);


/**
 * Compute the salted donor tax-id hash (SHA-512).
 *
 * @param donor_tax_id  cleartext donor tax id (ASCII/UTF-8)
 * @param salt          ASCII/UTF-8 salt
 * @param[out] out_hash buffer of size 512/8 bytes
 * @return true on success, false on invalid inputs
 */
bool
  DONAU_compute_salted_tax_id_hash (const char *donor_tax_id,
                                    const char *salt,
                                    unsigned char out_hash[512 / 8]);


/**
 * Greedily build a multiset of donation-unit public keys that sums EXACTLY to
 * @a requested_amount, using donation units from @a keys for the given @a year.
 *
 * @param keys              Donau keys (must match requested_amount currency)
 * @param requested_amount  target amount
 * @param year              only consider donation units for this year
 * @param[out] out_keys     array of selected public keys (owned by caller)
 * @param[out] out_len      length of @a out_keys
 * @return #GNUNET_OK on exact match;
 *         #GNUNET_NO if exact match not possible;
 *         #GNUNET_SYSERR on invalid input/currency mismatch.
 */
enum GNUNET_GenericReturnValue
DONAU_select_donation_unit_keys_for_amount (
  const struct DONAU_Keys *keys,
  const struct TALER_Amount *requested_amount,
  uint64_t year,
  struct DONAU_DonationUnitPublicKey **out_keys,
  uint32_t *out_len);


/**
 * Obtain the donation unit key details from the donau.
 *
 * @param keys the donau's key set
 * @param hc hash of the public key of the donation unit to lookup
 * @return details about the given donation unit key, returns NULL
 * if the key is not available or deprecated.
 */
const struct DONAU_DonationUnitInformation *
DONAU_get_donation_unit_key_by_hash (
  const struct DONAU_Keys *keys,
  const struct DONAU_DonationUnitHashP *hc);


/**
 * Obtain the donation amount for the given array of #DONAU_BlindedUniqueDonorIdentifierKeyPair
 *
 * @param keys the donau's key set
 * @param bkps array of blinded unique donor identifiers
 * @param num_bkps length of the @a bkps array
 * @param year year of the donation
 * @param[out] sum_out result amount (initialized to zero in @keys->currency)
 * @return #GNUNET_OK on success;
 *         #GNUNET_NO on invalid input, duplication, year mismatch;
 *         #GNUNET_SYSERR on math errors.
 */
enum GNUNET_GenericReturnValue
DONAU_get_donation_amount_from_bkps (
  const struct DONAU_Keys *keys,
  const struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps,
  size_t num_bkps,
  uint64_t year,
  struct TALER_Amount *sum_out);


/**
 * Get confirmation that the given array of the #DONAU_BlindedUniqueDonorIdentifierKeyPair
 * does not contain duplicates.
 *
 * @return #GNUNET_OK if the @a bkps array does not contain duplicates
 */
bool
DONAU_check_bkps_duplication (
  const struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps,
  const size_t num_bkps
  );


/**
 * Obtain meta data about an donau (online) signing
 * key.
 *
 * @param keys from where to obtain the meta data
 * @param donau_pub public key to lookup
 * @return NULL on error (@a donau_pub not known)
 */
const struct DONAU_SigningPublicKeyAndValidity *
DONAU_get_signing_key_info (
  const struct DONAU_Keys *keys,
  const struct DONAU_DonauPublicKeyP *donau_pub);


/* ********************* POST / issue receipt  *********************** */


/**
 * @brief A Batch Submit Handle
 */
struct DONAU_BatchIssueReceiptHandle;

/**
 * Structure with information about a batch
 * of issue receipts.
 */
struct DONAU_BatchIssueResponse
{
  /**
   * HTTP response data
   */
  struct DONAU_HttpResponse hr;

  union
  {

    /**
     * Information returned if the HTTP status is
     * #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * Blind signature provided by the donau
       */
      struct DONAU_BlindedDonationUnitSignature *blinded_sigs;

      /**
       * Number of blinded signatures in @a blinded_sigs.
       */
      size_t num_blinded_sigs;

      /**
       * total issued amount over all donation receipts of a donation specified
       * by the request (confirmation).
       */
      struct TALER_Amount issued_amount;

    } ok;

    struct
    {
      /* FIXME: returning full details is not implemented */
    } conflict;

  } details;
};


/**
 * Callbacks of this type are used to serve the result of submitting a
 *  permission request to a donau.
 *
 * @param cls closure
 * @param dr  response details
 */
typedef void
(*DONAU_BatchIssueReceiptsCallback) (
  void *cls,
  const struct DONAU_BatchIssueResponse*dr);


/**
 * Submit a batch of issue receipts to the donau and get the
 * donau's response. This API is typically used by a charity. Note that
 * while we return the response verbatim to the caller for further processing,
 * we do already verify that the response is well-formed (i.e. that signatures
 * included in the response are all valid). If the donau's reply is not
 * well-formed, we return an HTTP status code of zero to @a cb.
 *
 * We also verify that the signature of the charity is valid for this
 * request. Also, the donau must be ready to operate (i.e.  have
 * finished processing the /keys reply). If either check fails, we do
 * NOT initiate the receipts with the donau and instead return NULL.
 *
 * @param ctx curl context
 * @param url donau base URL
 * @param charity_priv private key of the charity
 * @param charity_id unique (row ID) of the charity at the DONAU
 * @param num_bkp length of the @a bkp array
 * @param bkp array with details about the blinded donation envelopes
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for the above callback
 * @param[out] ec if NULL is returned, set to the error code explaining why the operation failed
 * @return a handle for this request; NULL if the inputs are invalid (i.e.
 *         signatures fail to verify).  In this case, the callback is not called.
 */
struct DONAU_BatchIssueReceiptHandle *
DONAU_charity_issue_receipt (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  const struct DONAU_CharityPrivateKeyP *charity_priv,
  uint64_t charity_id,
  uint64_t year,
  size_t num_bkp,
  const struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkp,
  DONAU_BatchIssueReceiptsCallback cb,
  void *cb_cls);

/**
 * Cancel a batch issue receipt request. This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param[in] birh the issue receipt request handle
 */
void
DONAU_charity_issue_receipt_cancel (
  struct DONAU_BatchIssueReceiptHandle *birh);

/**
 * unblinded donation unit signature from Donau
 */
struct TALER_DonationUnitSignature
{
  /**
   * The unblinded signature
   */
  struct TALER_DenominationSignature sig;

};


/* ********************* POST / submit receipts  *********************** */


/**
 * @brief A Batch Submit receipts Handle
 */
struct DONAU_DonorReceiptsToStatementHandle;


/**
 * Structure with information about a batch
 * operation's result.
 */
struct DONAU_DonorReceiptsToStatementResult
{
  /**
   * HTTP response data
   */
  struct DONAU_HttpResponse hr;

};


/**
 * Callbacks of this type are used to serve the result of submitting a
 *  permission request to a donau.
 *
 * @param cls closure
 * @param dr  response details
 */
typedef void
(*DONAU_DonorReceiptsToStatementResultCallback) (
  void *cls,
  const struct DONAU_DonorReceiptsToStatementResult *dr);


/**
 * Submit a batch of receipts to the donau and get the
 * donau's response. This API is typically used by a donor. Note that
 * while we return the response verbatim to the caller for further processing,
 * we do already verify that the response is well-formed (i.e. that signatures
 * included in the response are all valid). If the donau's reply is not
 * well-formed, we return an HTTP status code of zero to @a cb.
 *
 * We also verify that the signature of the charity is valid for this
 * request. Also, the @a donau must be ready to operate (i.e.  have
 * finished processing the /keys reply). If either check fails, we do
 * NOT initiate the receipts with the donau and instead return NULL.
 *
 * @param ctx curl context
 * @param url donau base URL
 * @param num_drs length of the @a drs array
 * @param drs array with details about the donation receipts
 * @param year corresponding year
 * @param h_donor_tax_id salted and hashed tax id
 * @param cb the callback to call when a reply for this request is available
 * @param cls closure for the above callback
 * @param[out] ec if NULL is returned, set to the error code explaining why the operation failed
 * @return a handle for this request; NULL if the inputs are invalid (i.e.
 *         signatures fail to verify). In this case, the callback is not called.
 */
struct DONAU_DonorReceiptsToStatementHandle *
DONAU_donor_receipts_to_statement (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  const size_t num_drs,
  const struct DONAU_DonationReceipt drs[num_drs],
  const uint64_t year,
  const struct DONAU_HashDonorTaxId *h_donor_tax_id,
  DONAU_DonorReceiptsToStatementResultCallback cb,
  void *cls);

/**
 * Cancel a batch  permission request. This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param[in] the Batch Submit recipts handle
 */
void
DONAU_donor_receipts_to_statement_cancel (
  struct DONAU_DonorReceiptsToStatementHandle *);


/* ********************* GET /donation-statement *********************** */


/**
 * @brief A get donation statement Handle
 */
struct DONAU_DonationStatementGetHandle;


/**
 * Structure with information about a
 * operation's result.
 */
struct DONAU_DonationStatementResponse
{
  /**
   * HTTP response data
   */
  struct DONAU_HttpResponse hr;

  union
  {

    /**
     * Information returned if the HTTP status is
     * #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * total amount of the donation statement for the requested year
       */
      struct TALER_Amount total_amount;

      /**
       * The donation statment for a requested year. Signature over the total amount,
       * the year, the unique identifier hash
       */
      struct DONAU_DonauSignatureP donation_statement_sig;

      /**
       * The donau public to verify the signature.
       */
      struct DONAU_DonauPublicKeyP donau_pub;

    } ok;

  } details;
};


/**
 * Callbacks of this type are used to serve the result of submitting a
 *  permission request to a donau.
 *
 * @param cls closure
 * @param dr  response details
 */
typedef void
(*DONAU_GetDonationStatmentResponseCallback) (
  void *cls,
  const struct DONAU_DonationStatementResponse *dr);


/**
 * Get a specific donation statement from the donau. This API is typically used by a donor.
 * Note that while we return the response verbatim to the caller for further processing,
 * we do already verify that the response is well-formed (i.e. that signatures
 * included in the response are all valid). If the donau's reply is not
 * well-formed, we return an HTTP status code of zero to @a cb.
 *
 * @param ctx curl context
 * @param url donau base URL
 * @param year corresponding year
 * @param h_donor_tax_id salted and hashed tax id
 * @param cb the callback to call when a reply for this request is available
 * @param cls closure for the above callback
 * @param[out] ec if NULL is returned, set to the error code explaining why the operation failed
 * @return a handle for this request; NULL if the inputs are invalid (i.e.
 *         signatures fail to verify). In this case, the callback is not called.
 */
struct DONAU_DonationStatementGetHandle *
DONAU_donation_statement_get (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  const uint64_t year,
  const struct DONAU_HashDonorTaxId *h_donor_tax_id,
  DONAU_GetDonationStatmentResponseCallback cb,
  void *cb_cls);

/**
 * Cancel a batch  permission request. This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param[in] the Batch Submit recipts handle
 */
void
DONAU_donation_statement_get_cancel (
  struct DONAU_DonationStatementGetHandle *);


/* ********************* POST /csr batch-issue *********************** */


/**
 * @brief A /csr-batch-issue Handle
 */
struct DONAU_CsRBatchIssueHandle;


/**
 * Details about a response for a CS R request.
 */
struct DONAU_CsRBatchIssueResponse
{
  /**
   * HTTP response data.
   */
  struct DONAU_HttpResponse hr;

  /**
   * Details about the response.
   */
  union
  {
    /**
     * Details if the status is #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * Values contributed by the donau for the
       * respective donation receipts's batch-issue operation.
       */
      struct DONAU_BatchIssueValues alg_values;

    } ok;

    /**
     * Details if the status is #MHD_HTTP_GONE.
     */
    struct
    {
      /* FIXME: returning full details is not implemented */
    } gone;

  } details;
};


/**
 * Callbacks of this type are used to serve the result of submitting a
 * CS R batch-issue request to a donau.
 *
 * @param cls closure
 * @param csrr response details
 */
typedef void
(*DONAU_CsRBatchIssueCallback) (
  void *cls,
  const struct DONAU_CsRBatchIssueResponse *csrr);


/**
 * Get a CS R using a /csr-batch-issue request.
 *
 * @param curl_ctx The curl context to use for the requests
 * @param donau_url Base-URL to the donau
 * @param pk Which donation unit key is the /csr request for
 * @param nonce client nonce for the request
 * @param res_cb the callback to call when the final result for this request is available
 * @param res_cb_cls closure for the above callback
 * @return handle for the operation on success, NULL on error, i.e.
 *         if the inputs are invalid (i.e.donation unit key not with this donau).
 *         In this case, the callback is not called.
 */
struct DONAU_CsRBatchIssueHandle *
DONAU_csr_issue (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  const struct DONAU_DonationUnitPublicKey *pk,
  const struct GNUNET_CRYPTO_CsSessionNonce *nonce,
  DONAU_CsRBatchIssueCallback cb,
  void *cb_cls);


/**
 *
 * Cancel a CS R batch-issue request.  This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param csrh the batch-issue handle
 */
void
DONAU_csr_cancel (
  struct DONAU_CsRBatchIssueHandle *csrh);


/* ********************* GET /charities/ *********************** */

/**
 *  A Charity
 */
struct DONAU_CharitySummary
{
  /**
   * charity id
   */
  uint64_t charity_id;

  /**
   * charity name
   */
  const char *name;

  /**
   * Max donation amout for this charitiy and year.
   */
  struct TALER_Amount max_per_year;

  /**
   * Current donation amount for this charity and year.
   */
  struct TALER_Amount receipts_to_date;

};


/**
 * @brief A /charities/ GET Handle
 */
struct DONAU_CharitiesGetHandle;


/**
 * @brief summary of every charity
 */
struct DONAU_GetCharitiesResponse
{

  /**
   * High-level HTTP response details.
   */
  struct DONAU_HttpResponse hr;

  /**
   * Details depending on @e hr.http_status.
   */
  union
  {

    /**
     * Information returned on success, if
     * @e hr.http_status is #MHD_HTTP_OK
     */
    struct
    {

      /**
       * Charity status information.
       */
      struct DONAU_CharitySummary *charities;

      /**
       * Length of the @e charities array.
       */
      size_t num_charities;

    } ok;

  } details;

};


/**
 * Callbacks of this type are used to serve the result of
 * charities status request to a donau.
 *
 * @param cls closure
 * @param rs HTTP response data
 */
typedef void
(*DONAU_GetCharitiesResponseCallback) (
  void *cls,
  const struct DONAU_GetCharitiesResponse *rs);


/**
 * Submit a request to obtain the transaction history of a charity
 * from the donau. Note that while we return the full response to the
 * caller for further processing, we do already verify that the
 * response is well-formed (i.e. that signatures included in the
 * response are all valid). If the donau's reply is not well-formed,
 * we return an HTTP status code of zero to @a cb.
 *
 * @param ctx curl context
 * @param url donau base URL
 * @param bearer for authorization
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for the above callback
 * @return a handle for this request; NULL if the inputs are invalid (i.e.
 *         signatures fail to verify). In this case, the callback is not called.
 */
struct DONAU_CharitiesGetHandle *
DONAU_charities_get (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  const struct DONAU_BearerToken *bearer,
  DONAU_GetCharitiesResponseCallback cb,
  void *cb_cls);


/**
 * Cancel a charity GET request.  This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param rgh the charity request handle
 */
void
DONAU_charities_get_cancel (
  struct DONAU_CharitiesGetHandle *rgh);


/* ********************* GET /charities/$CHARITY_ID *********************** */

/**
 * Information about a charity
 */
struct DONAU_Charity
{
  /**
   * name of the charity
   */
  const char *name;

  /**
   * charity url
   */
  const char *charity_url;

  /**
   * public key of the charity
   */
  struct DONAU_CharityPublicKeyP charity_pub;

  /**
    * Max donation amout for this charitiy and @e current_year.
    */
  struct TALER_Amount max_per_year;

  /**
   * Current amount of donation receipts for @e current_year.
   */
  struct TALER_Amount receipts_to_date;

  /**
   * current year
   */
  uint64_t current_year;

};


/**
 * @brief A /charities/$CHARITY_ID GET Handle
 */
struct DONAU_CharityGetHandle;


/**
 * @brief summary of a charity
 */
struct DONAU_GetCharityResponse
{

  /**
   * High-level HTTP response details.
   */
  struct DONAU_HttpResponse hr;

  /**
   * Details depending on @e hr.http_status.
   */
  union
  {

    /**
     * Information returned on success, if
     * @e hr.http_status is #MHD_HTTP_OK
     */
    struct
    {

      /**
       * Charity status information.
       */
      struct DONAU_Charity charity;


    } ok;

  } details;

};


/**
 * Callbacks of this type are used to serve the result of a
 * charity status request to a donau.
 *
 * @param cls closure
 * @param rs HTTP response data
 */
typedef void
(*DONAU_GetCharityResponseCallback) (
  void *cls,
  const struct DONAU_GetCharityResponse *rs);


/**
 * Submit a GET request to obtain the informations about a single charity
 * from the donau. Note that while we return the full response to the
 * caller for further processing, we do already verify that the
 * response is well-formed (i.e. that signatures included in the
 * response are all valid). If the donau's reply is not well-formed,
 * we return an HTTP status code of zero to @a cb.
 *
 * @param ctx curl context
 * @param url donau base URL
 * @param id of the requested charity
 * @param charity_priv private key of the charity, for authorization
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for the above callback
 * @return a handle for this request; NULL if the inputs are invalid (i.e.
 *         signatures fail to verify).  In this case, the callback is not called.
 */
struct DONAU_CharityGetHandle *
DONAU_charity_get (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  uint64_t id,
  const struct DONAU_CharityPrivateKeyP *charity_priv,
  DONAU_GetCharityResponseCallback cb,
  void *cb_cls);


/**
 * Cancel a charity GET request. This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param rgh the charity request handle
 */
void
DONAU_charity_get_cancel (
  struct DONAU_CharityGetHandle *rgh);


/* ********************* POST /charities/ *********************** */

/**
 * @brief A /charities Post Handle
 */
struct DONAU_CharityPostHandle;


/**
 * @brief new charity ID Response
 */
struct DONAU_PostCharityResponse
{

  /**
   * High-level HTTP response details.
   */
  struct DONAU_HttpResponse hr;

  /**
   * Details depending on @e hr.http_status.
   */
  union
  {

    /**
     * Information returned on success, if
     * @e hr.http_status is #MHD_HTTP_CREATED
     */
    struct
    {

      /**
       * charity id
       */
      uint64_t charity_id;

    } ok;

  } details;

};


/**
 * Callbacks of this type are used to serve the result of a
 * charity post request to a donau.
 *
 * @param cls closure
 * @param rs HTTP response data
 */
typedef void
(*DONAU_PostCharityResponseCallback) (
  void *cls,
  const struct DONAU_PostCharityResponse *rs);


/**
 * Submit a POST request to add a new charity to the donau. Note that
 * while we return the full response to the caller for further processing,
 * we do already verify that the response is well-formed (i.e. that
 * signatures included in the response are all valid).  If the donau's
 * reply is not well-formed, we return an HTTP status code of zero to
 * @a cb.
 *
 * @param ctx curl context
 * @param url donau base URL
 * @param charity_name human readable name of the charity
 * @param charity_url Web site of the charity
 * @param max_per_year max donation amount allowed for the charity per year
 * @param charity_pub public key of the charity
 * @param bearer for authorization
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for the above callback
 * @return a handle for this request; NULL if the inputs are invalid (i.e.
 *         signatures fail to verify).  In this case, the callback is not called.
 */
struct DONAU_CharityPostHandle *
DONAU_charity_post (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  const char *charity_name,
  const char *charity_url,
  const struct TALER_Amount *max_per_year,
  const struct DONAU_CharityPublicKeyP *charity_pub,
  const struct DONAU_BearerToken *bearer,
  DONAU_PostCharityResponseCallback cb,
  void *cb_cls);

/**
 * Cancel a charity Post request. This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param rgh the charity post handle
 */
void
DONAU_charity_post_cancel (
  struct DONAU_CharityPostHandle *rgh);


/* ********************* PATCH /charities/$CHARITY_ID *********************** */


/**
 * @brief A /charities/$CHARITY_ID Patch Handle
 */
struct DONAU_CharityPatchHandle;


/**
 * @brief charity patch response
 */
struct DONAU_PatchCharityResponse
{

  /**
   * High-level HTTP response details.
   */
  struct DONAU_HttpResponse hr;

};


/**
 * Callbacks of this type are used to serve the result of a
 * charity post request to a donau.
 *
 * @param cls closure
 * @param rs HTTP response data
 */
typedef void
(*DONAU_PatchCharityResponseCallback) (
  void *cls,
  const struct DONAU_PatchCharityResponse *rs);


/**
 * Submit a PATCH request to change data about a charity
 * from the donau. Note that while we return the full response to the
 * caller for further processing, we do already verify that the
 * response is well-formed (i.e. that signatures included in the
 * response are all valid). If the donau's reply is not well-formed,
 * we return an HTTP status code of zero to @a cb.
 *
 * @param ctx curl context
 * @param url donau base URL
 * @param charity_id of the charity
 * @param charity_name human readable name of the charity
 * @param charity_url Web site of the charity
 * @param max_per_year max donation amount allowed for the charity per year
 * @param charity_pub public key of the charity
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for the above callback
 * @return a handle for this request; NULL if the inputs are invalid (i.e.
 *         signatures fail to verify).  In this case, the callback is not called.
 */
struct DONAU_CharityPatchHandle *
DONAU_charity_patch (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  const uint64_t charity_id,
  const char *charity_name,
  const char *charity_url,
  const struct TALER_Amount *max_per_year,
  const struct DONAU_CharityPublicKeyP *charity_pub,
  const struct DONAU_BearerToken *bearer,
  DONAU_PatchCharityResponseCallback cb,
  void *cb_cls);

/**
 * Cancel a charity Patch request. This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param rgh the charity patch handle
 */
void
DONAU_charity_patch_cancel (
  struct DONAU_CharityPatchHandle *rgh);


/* ********************* DELETE /charities/$CHARITY_ID *********************** */

/**
 * @brief A /charities/$CHARITY_ID Delete Handle
 */
struct DONAU_CharityDeleteHandle;


/**
 * @brief new charity ID Response
 */
struct DONAU_DeleteCharityResponse
{

  /**
   * High-level HTTP response details.
   */
  struct DONAU_HttpResponse hr;

};


/**
 * Callbacks of this type are used to serve the result of a
 * charity post request to a donau.
 *
 * @param cls closure
 * @param rs HTTP response data
 */
typedef void
(*DONAU_DeleteCharityResponseCallback) (
  void *cls,
  const struct DONAU_DeleteCharityResponse *rs);


/**
 * Submit a DELETE request to delete a charity
 * from the donau. Note that while we return the full response to the
 * caller for further processing, we do already verify that the
 * response is well-formed (i.e. that signatures included in the
 * response are all valid). If the donau's reply is not well-formed,
 * we return an HTTP status code of zero to @a cb.
 *
 * @param ctx curl context
 * @param url donau base URL
 * @param id of the charity
 * @param bearer for authorization
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for the above callback
 * @return a handle for this request; NULL if the inputs are invalid (i.e.
 *         signatures fail to verify). In this case, the callback is not called.
 */
struct DONAU_CharityDeleteHandle *
DONAU_charity_delete (
  struct GNUNET_CURL_Context *ctx,
  const char *url,
  const uint64_t id,
  const struct DONAU_BearerToken *bearer,
  DONAU_DeleteCharityResponseCallback cb,
  void *cb_cls);

/**
 * Cancel a charity Delete request. This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param rgh the charity request handle
 */
void
DONAU_charity_delete_cancel (
  struct DONAU_CharityDeleteHandle *rgh);

#endif
