/*
  This file is part of TALER
  Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors)
  TALER is free software; you can redistribute it and/or modify it under the
  terms of the GNU 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 General Public License for more details.
  You should have received a copy of the GNU General Public License along with
  TALER; see the file COPYING.  If not, If not, see
  
*/
/**
 * @file mint-lib/mint_api.c
 * @brief Implementation of the client interface to mint's HTTP API
 * @author Sree Harsha Totakura 
 */
#include "platform.h"
#include 
#include 
#include 
#include "taler_mint_service.h"
#include "taler_signatures.h"
// leftovers follow...
/**
 * Log error related to CURL operations.
 *
 * @param type log level
 * @param function which function failed to run
 * @param code what was the curl error code
 */
#define CURL_STRERROR(type, function, code)      \
 GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", \
             function, __FILE__, __LINE__, curl_easy_strerror (code));
/**
 * Print JSON parsing related error information
 */
#define JSON_WARN(error)                                                \
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,                              \
                "JSON parsing failed at %s:%u: %s (%s)",                \
                __FILE__, __LINE__, error.text, error.source)
/**
 * Failsafe flag. Raised if our constructor fails to initialize
 * the Curl library.
 */
static int TALER_MINT_curl_fail;
/**
 * A handle to submit a deposit permission and get its status
 */
struct TALER_MINT_DepositHandle
{
  /**
   *The connection to mint this request handle will use
   */
  struct TALER_MINT_Handle *mint;
  /**
   * The url for this handle
   */
  char *url;
  TALER_MINT_DepositResultCallback cb;
  void *cb_cls;
  char *json_enc;
  struct curl_slist *headers;
};
#define EXITIF(cond)                                              \
  do {                                                            \
    if (cond) { GNUNET_break (0); goto EXITIF_exit; }             \
  } while (0)
static int
parse_deposit_response (void *buf, size_t size, int *r_status, json_t **r_obj)
{
  json_t *obj;
  const char *status_str;
  json_error_t error;
  status_str = NULL;
  obj = NULL;
  obj = json_loadb (buf, size,
                    JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, &error);
  if (NULL == obj)
  {
    JSON_WARN (error);
    return GNUNET_SYSERR;
  }
  EXITIF (-1 == json_unpack (obj, "{s:s}", "status", &status_str));
  TALER_LOG_DEBUG ("Received deposit response: %s from mint\n", status_str);
  if (0 == strcmp ("DEPOSIT_OK", status_str))
    *r_status = 1;
  else if (0 == strcmp ("DEPOSIT_QUEUED", status_str))
    *r_status = 2;
  else
    *r_status = 0;
  *r_obj = obj;
  return GNUNET_OK;
 EXITIF_exit:
  json_decref (obj);
  return GNUNET_SYSERR;
}
#undef EXITIF
/**
 * Submit a deposit permission to the mint and get the mint's response
 *
 * @param mint the mint handle
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for the above callback
 * @param deposit_obj the deposit permission received from the customer along
 *         with the wireformat JSON object
 * @return a handle for this request; NULL if the JSON object could not be
 *         parsed or is of incorrect format or any other error.  In this case,
 *         the callback is not called.
 */
struct TALER_MINT_DepositHandle *
TALER_MINT_deposit_submit_json (struct TALER_MINT_Handle *mint,
                                TALER_MINT_DepositResultCallback cb,
                                void *cb_cls,
                                json_t *deposit_obj)
{
  struct TALER_MINT_DepositHandle *dh;
  GNUNET_assert (REQUEST_TYPE_NONE == mint->req_type);
  dh = GNUNET_new (struct TALER_MINT_DepositHandle);
  dh->mint = mint;
  mint->req_type = REQUEST_TYPE_DEPOSIT;
  mint->req.deposit = dh;
  dh->cb = cb;
  dh->cb_cls = cb_cls;
  GNUNET_asprintf (&dh->url, "http://%s:%hu/deposit", mint->hostname, mint->port);
  GNUNET_assert (NULL != (dh->json_enc = json_dumps (deposit_obj, JSON_COMPACT)));
  GNUNET_assert (CURLE_OK ==
                 curl_easy_setopt (mint->curl, CURLOPT_URL, dh->url));
  GNUNET_assert (CURLE_OK ==
                 curl_easy_setopt (mint->curl, CURLOPT_POSTFIELDS,
                                   dh->json_enc));
  GNUNET_assert (CURLE_OK ==
                 curl_easy_setopt (mint->curl, CURLOPT_POSTFIELDSIZE,
                                   strlen (dh->json_enc)));
  GNUNET_assert (NULL != (dh->headers =
                          curl_slist_append (dh->headers, "Content-Type: application/json")));
  GNUNET_assert (CURLE_OK ==
                 curl_easy_setopt (mint->curl, CURLOPT_HTTPHEADER, dh->headers));
  if (GNUNET_NO == mint->connected)
    mint_connect (mint);
  perform_now (mint->ctx);
  return dh;
}
/* end of mint_api.c */