#include <webconnection.h>

/* TODO
 * From https://nominatim.org/release-docs/develop/api/Search/
 * Language of results
 * accept-language=<browser language string>
 * Preferred language order for showing search results, overrides the value specified in the "Accept-Language" HTTP header.
 * Either use a standard RFC2616 accept-language string or a simple comma-separated list of language codes.
 */

/* Below is needes for Curl to cummunicate with Nominatim */
struct MemoryStruct {
  char *memory;
  size_t size;
};

/* some shit from curl I still don’t get... */
size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
  size_t realsize = size * nmemb;
  struct MemoryStruct *mem = (struct MemoryStruct *)userp;

  char *ptr = realloc(mem->memory, mem->size + realsize + 1);
  if(ptr == NULL) {
    /* out of memory! */
    printf("not enough memory (realloc returned NULL)\n");
    return 0;
  }

  mem->memory = ptr;
  memcpy(&(mem->memory[mem->size]), contents, realsize);
  mem->size += realsize;
  mem->memory[mem->size] = 0;

  return realsize;
}

/* TODO
 * Make this function look nicer */
struct Output *search_nominatim (const gchar *searchtext){

  CURL *curl;
  CURLcode res;

  struct Output nullOutput = {NULL,0.0,0.0};
  struct Output *output = &nullOutput;

	struct MemoryStruct chunk;
	chunk.memory = malloc(1);
	chunk.size = 0;

  curl_global_init(CURL_GLOBAL_DEFAULT);
  curl = curl_easy_init();

  if(curl) {
		/* Bring the entered words into the API form of NOMINATIM see
		 * https://nominatim.org/release-docs/develop/api/Search/
		 * for further information */

		char *URLsearch = curl_easy_escape(curl, searchtext, 0);
		char *URLosm = "https://nominatim.openstreetmap.org/search?q=";
		char *URLformat = "&format=geojson";
		char *URL = (char *) malloc(1+strlen(URLsearch)+strlen(URLosm)+strlen(URLformat));
		strcpy(URL,URLosm);
		strcat(URL,URLsearch);
		strcat(URL,URLformat);
		g_print ("%s\n", URL);
    curl_easy_setopt(curl, CURLOPT_URL, URL);
		/* Nominatim NEEDS a Useragent! */
		curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.58.0");
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

    /* Perform the request, res will get the return code */
		res = curl_easy_perform(curl);

		/* Check for errors */
		if(res != CURLE_OK)
			{
		  	g_print("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
			}
		else
			{
				/* Convert the JSON file which is handed back by nominatim
				 * into double variables for the north and east component */
				g_print("\nParsing location\n");
				json_object *json = json_tokener_parse(chunk.memory);
				json_object *jsonFeatures;
				json_object *jsonEntry;
				json_object *jsonGeometry;
				json_object *jsonCoordinates;
				json_object *jsonProperties;
				json_object *jsonDisplayName;

				json_object_object_get_ex(json, "features", &jsonFeatures);
				jsonEntry = json_object_array_get_idx(jsonFeatures, 0);

				json_object_object_get_ex(jsonEntry, "geometry", &jsonGeometry);
				json_object_object_get_ex(jsonGeometry, "coordinates", &jsonCoordinates);
				(*output).east = json_object_get_double(json_object_array_get_idx(jsonCoordinates, 0));
				(*output).north = json_object_get_double(json_object_array_get_idx(jsonCoordinates, 1));

				json_object_object_get_ex(jsonEntry, "properties", &jsonProperties);
				json_object_object_get_ex(jsonProperties, "display_name", &jsonDisplayName);
				(*output).displayText = json_object_get_string(jsonDisplayName);

				/*
         * g_print("Display Text: %s, North: %f, East: %f\n",(*output).displayText, (*output).east, (*output).north);
        */
        return output;
			}
		curl_easy_cleanup(curl);
  }
  curl_global_cleanup();

  return output;
}

