/*
  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 Lesser General Public License as published by the Free Software
  Foundation; either version 2.1, 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 Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License along with
  TALER; see the file COPYING.LGPL.  If not, see
  <http://www.gnu.org/licenses/>
*/
/**
 * @file include/taler/taler-merchant/common.h
 * @brief Common functions of libtalermerchant not specific to a particular endpoint
 * @author Christian Grothoff
 */
#ifndef _TALER_MERCHANT__COMMON_H
#define _TALER_MERCHANT__COMMON_H

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


/**
 * Maximum number of options that can be set in one set_options
 * call. Used as a dummy for "infinite" in the varargs case.
 */
#define TALER_MERCHANT_COMMON_OPTIONS_ARRAY_MAX_SIZE UINT_MAX


/**
 * General information about the HTTP response we obtained
 * from the merchant for a request.
 */
struct TALER_MERCHANT_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 merchant 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;

  /**
   * HTTP status code returned by the exchange, if
   * the merchant forwarded an exchange error to us.
   * Set to 0 if there was no exchange involved.
   */
  unsigned int exchange_http_status;

  /**
   * JSON reply from the exchange, if the merchant
   * forwarded an exchange error to us. NULL otherwise.
   */
  const json_t *exchange_reply;

  /**
   * Taler error code from the exchange, if the merchant
   * forwarded an exchange error to us.
   */
  enum TALER_ErrorCode exchange_code;

  /**
   * Human-readable hint from the exchange, if the merchant
   * forwarded an exchange error to us. NULL otherwise.
   */
  const char *exchange_hint;

};


/**
 * Parse URI data for taler://pay/ URIs.
 */
struct TALER_MERCHANT_PayUriData
{

  /**
   * Hostname (and possibly port) of the merchant backend.
   */
  char *merchant_host;

  /**
   * Prefix path at the merchant backend (may be NULL).
   */
  char *merchant_prefix_path;

  /**
   * The order ID.
   */
  char *order_id;

  /**
   * The session ID (may be NULL if none given).
   */
  char *session_id;

  /**
   * Claim token (may be NULL if not given in the URI).
   */
  struct TALER_ClaimTokenP *claim_token;

  /**
   * Subscription session ID (SSID), may be NULL.
   */
  char *ssid;

  /**
   * Set to true if taler+http:// was used (test only).
   */
  bool use_http;

};


/**
 * Parse URI data for taler://refund/ URIs.
 */
struct TALER_MERCHANT_RefundUriData
{

  /**
   * Hostname (and possibly port) of the merchant backend.
   */
  char *merchant_host;

  /**
   * Prefix path at the merchant backend (may be NULL).
   */
  char *merchant_prefix_path;

  /**
   * The order ID.
   */
  char *order_id;

  /**
   * Subscription session ID (SSID), may be NULL.
   */
  char *ssid;

  /**
   * Set to true if taler+http:// was used (test only).
   */
  bool use_http;

};

/**
 * Entry for one measurement unit.
 */
struct TALER_MERCHANT_UnitEntry
{

  /**
   * Identifier of the unit.
   */
  const char *unit;

  /**
   * Long (human-readable) name of the unit.
   */
  const char *unit_name_long;

  /**
   * Short symbol for the unit.
   */
  const char *unit_name_short;

  const json_t *unit_name_long_i18n;

  const json_t *unit_name_short_i18n;

  /**
   * Whether fractional quantities are allowed.
   */
  bool unit_allow_fraction;

  /**
   * Precision level for fractional quantities.
   */
  uint32_t unit_precision_level;

  /**
   * Whether this unit is currently active.
   */
  bool unit_active;

  bool unit_builtin;
};


/**
 * Type of a statistics metric / aggregation mode.
 */
enum TALER_MERCHANT_StatisticsType
{
  /**
   * Return statistics aggregated by bucket.
   */
  TALER_MERCHANT_STATISTICS_BY_BUCKET = 0,

  /**
   * Return statistics aggregated by time interval.
   */
  TALER_MERCHANT_STATISTICS_BY_INTERVAL = 1,

  /**
   * Return all available statistics (both buckets and intervals).
   */
  TALER_MERCHANT_STATISTICS_ALL = 2
};


/**
 * Parse a taler://pay/ URI into its components.
 *
 * @param pay_uri the URI to parse
 * @param[out] parse_data parsed URI data, to be freed with
 *             #TALER_MERCHANT_parse_pay_uri_free()
 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
 */
enum GNUNET_GenericReturnValue
TALER_MERCHANT_parse_pay_uri (const char *pay_uri,
                              struct TALER_MERCHANT_PayUriData *parse_data);


/**
 * Free a #TALER_MERCHANT_PayUriData previously obtained from
 * #TALER_MERCHANT_parse_pay_uri().
 *
 * @param[in] parse_data the data to free (fields only, not the struct itself)
 */
void
TALER_MERCHANT_parse_pay_uri_free (
  struct TALER_MERCHANT_PayUriData *parse_data);


/**
 * Parse a taler://refund/ URI into its components.
 *
 * @param refund_uri the URI to parse
 * @param[out] parse_data parsed URI data, to be freed with
 *             #TALER_MERCHANT_parse_refund_uri_free()
 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
 */
enum GNUNET_GenericReturnValue
TALER_MERCHANT_parse_refund_uri (
  const char *refund_uri,
  struct TALER_MERCHANT_RefundUriData *parse_data);


/**
 * Free a #TALER_MERCHANT_RefundUriData previously obtained from
 * #TALER_MERCHANT_parse_refund_uri().
 *
 * @param[in] parse_data the data to free (fields only, not the struct itself)
 */
void
TALER_MERCHANT_parse_refund_uri_free (
  struct TALER_MERCHANT_RefundUriData *parse_data);


/**
 * Format a quantity into its decimal string representation.
 *
 * @param quantity integer part of the quantity
 * @param quantity_frac fractional part
 * @param[out] buffer output buffer
 * @param buffer_length size of @a buffer
 */
void
TALER_MERCHANT_format_quantity_string (uint64_t quantity,
                                       uint32_t quantity_frac,
                                       char *buffer,
                                       size_t buffer_length);


/**
 * Format a stock value into its decimal string representation.
 *
 * @param total_stock integer part of the stock value
 * @param total_stock_frac fractional part
 * @param[out] buffer output buffer
 * @param buffer_length size of @a buffer
 */
void
TALER_MERCHANT_format_stock_string (uint64_t total_stock,
                                    uint32_t total_stock_frac,
                                    char *buffer,
                                    size_t buffer_length);


#endif
