#ifndef HTTP_C
#define HTTP_C

#include "allocator.c"
#include "utils.c"
#include <curl/curl.h>

typedef struct {
  byte_t *data;
  size_t size;
} byte_sized_t;

void byte_sized_free(byte_sized_t **b) {
  if (b != NULL && *b != NULL) {
    free((*b)->data);
    (*b)->data = NULL;
    (*b)->size = 0;
    free(*b);
    *b = NULL;
  }
}

static size_t http_write_callback(void *contents, size_t size, size_t nmemb,
                                  void *userp) {
  size_t realsize = size * nmemb;
  byte_sized_t **buffer = (byte_sized_t **)userp;

  byte_t *new_buffer = malloc(realsize);
  if (new_buffer == NULL) {
    return 0;
  }

  if (*buffer == NULL) {
    *buffer = malloc(sizeof(byte_sized_t));
    (*buffer)->data = new_buffer;
    (*buffer)->size = realsize;

    memcpy((*buffer)->data, contents, realsize);
  } else {
    byte_t *combined_buffer = malloc((*buffer)->size + realsize);
    if (combined_buffer == NULL) {
      free(new_buffer);
      return 0;
    }

    memcpy(combined_buffer, (*buffer)->data, (*buffer)->size);
    memcpy(combined_buffer + (*buffer)->size, contents, realsize);

    free((*buffer)->data);
    (*buffer)->data = combined_buffer;
    (*buffer)->size += realsize;

    free(new_buffer);
  }

  return realsize;
}

byte_sized_t *http_get(char *url) {
  byte_sized_t *buffer = NULL;

  defer(curl_easy_cleanup) CURL *curl = curl_easy_init();
  if (!curl) {
    return NULL;
  }

  curl_easy_setopt(curl, CURLOPT_URL, url);
  curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);

  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_write_callback);
  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
  curl_easy_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0);

  CURLcode res = curl_easy_perform(curl);
  if (res != CURLE_OK) {
    return NULL;
  }

  return buffer;
}

int http_post(const char *url, char *data) {
  defer(curl_easy_cleanup) CURL *curl = curl_easy_init();
  if (!curl) {
    return 1;
  }

  curl_easy_setopt(curl, CURLOPT_URL, url);
  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
  curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);

  CURLcode res = curl_easy_perform(curl);
  if (res != CURLE_OK) {
    return 1;
  }

  return 0;
}

#endif
