/* ****************************************************************************
*
* httpRequestSend - 
*
* RETURN VALUES
*   httpRequestSend returns 0 on success and a negative number on failure:
*     -1: Invalid port
*     -2: Invalid IP
*     -3: Invalid verb
*     -4: Invalid resource
*     -5: No Content-Type BUT content present
*     -6: Content-Type present but there is no content
*     -7: Total outgoing message size is too big
*     -8: Unable to initialize libcurl
*     -9: Error making HTTP request
*
*   [ error codes -1 to -7 comes from httpRequestSendWithCurl ]
*/
int httpRequestSend
(
   const std::string&     _ip,
   unsigned short         port,
   const std::string&     protocol,
   const std::string&     verb,
   const std::string&     tenant,
   const std::string&     servicePath,
   const std::string&     xauthToken,
   const std::string&     resource,
   const std::string&     orig_content_type,
   const std::string&     content,
   const std::string&     fiwareCorrelation,
   const std::string&     ngisv2AttrFormat,
   bool                   useRush,
   bool                   waitForResponse,
   std::string*           outP,
   const std::string&     acceptFormat,
   long                   timeoutInMilliseconds
)
{
  struct curl_context  cc;
  int                  response;

  get_curl_context(_ip, &cc);
  if (cc.curl == NULL)
  {
    release_curl_context(&cc);
    LM_E(("Runtime Error (could not init libcurl)"));
    lmTransactionEnd();

    *outP = "error";
    return -8;
  }

  response = httpRequestSendWithCurl(cc.curl,
                                     _ip,
                                     port,
                                     protocol,
                                     verb,
                                     tenant,
                                     servicePath,
                                     xauthToken,
                                     resource,
                                     orig_content_type,
                                     content,
                                     fiwareCorrelation,
                                     ngisv2AttrFormat,
                                     useRush,
                                     waitForResponse,
                                     outP,
                                     acceptFormat,
                                     timeoutInMilliseconds);
  release_curl_context(&cc);
  return response;
}
/* ****************************************************************************
*
* QueueWorkers::start() -
*/
static void *workerFunc(void* pSyncQ)
{
  SyncQOverflow<SenderThreadParams*> *queue = (SyncQOverflow<SenderThreadParams*> *) pSyncQ;
  CURL *curl;

  // Initialize curl context
  curl = curl_easy_init();

  if (curl == NULL)
  {
    LM_E(("Runtime Error (curl_easy_init)"));
    pthread_exit(NULL);
  }

  for (;;)
  {
    SenderThreadParams* params = queue->pop();
    struct timespec     now;
    struct timespec     howlong;
    size_t              estimatedQSize;

    QueueStatistics::incOut();
    clock_gettime(CLOCK_REALTIME, &now);
    clock_difftime(&now, &params->timeStamp, &howlong);
    estimatedQSize = queue->size();
    QueueStatistics::addTimeInQWithSize(&howlong, estimatedQSize);


    strncpy(transactionId, params->transactionId, sizeof(transactionId));

    LM_T(LmtNotifier, ("worker sending to: host='%s', port=%d, verb=%s, tenant='%s', service-path: '%s', xauthToken: '%s', path='%s', content-type: %s",
                       params->ip.c_str(),
                       params->port,
                       params->verb.c_str(),
                       params->tenant.c_str(),
                       params->servicePath.c_str(),
                       params->xauthToken.c_str(),
                       params->resource.c_str(),
                       params->content_type.c_str()));

    if (simulatedNotification)
    {
      LM_T(LmtNotifier, ("simulatedNotification is 'true', skipping outgoing request"));
      __sync_fetch_and_add(&noOfSimulatedNotifications, 1);
    }
    else // we'll send the notification
    {
      std::string  out;
      int          r;

      r =  httpRequestSendWithCurl(curl,
                                   params->ip,
                                   params->port,
                                   params->protocol,
                                   params->verb,
                                   params->tenant,
                                   params->servicePath,
                                   params->xauthToken,
                                   params->resource,
                                   params->content_type,
                                   params->content,
                                   true,
                                   NOTIFICATION_WAIT_MODE,
                                   &out);

      //
      // FIXME: ok and error counter should be incremented in the other notification modes (generalizing the concept, i.e.
      // not as member of QueueStatistics:: which seems to be tied to just the threadpool notification mode)
      //
      if (r == 0)
      {
        statisticsUpdate(NotifyContextSent, params->format);
        QueueStatistics::incSentOK();
      }
      else
      {
        QueueStatistics::incSentError();
      }

    }

    // Free params memory
    delete params;

    // Reset curl for next iteration
    curl_easy_reset(curl);
  }
}