+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cloud/cloud_lap_request.h"
+#include "cloud/http_request.h"
+#include "cloud/lap_info_serializer.h"
+#include "cloud/lap_info.h"
+#include <glib.h>
+#include <gio/gio.h>
+#include <string.h>
+#include "log.h"
+
+#define BASE_URL "http://son.tizen.online"
+#define PATH_API_LAP "/api/lap"
+
+typedef struct {
+ char *ap_mac;
+ cloud_request_lap_list_data_cb cb;
+ void *user_data;
+} lap_api_get_request_context_t;
+
+typedef struct {
+ lap_info_t *lap;
+ cloud_request_lap_post_finish_cb cb;
+ void *user_data;
+} lap_api_post_request_context_t;
+
+typedef struct {
+ long response_code;
+ char *response_msg;
+} lap_api_post_request_response_t;
+
+typedef struct {
+ long response_code;
+ lap_info_t **laps;
+ int size;
+} lap_api_get_request_response_t;
+
+static void lap_api_post_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable);
+static void lap_api_post_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data);
+static void lap_api_post_task_context_free(lap_api_post_request_context_t *context);
+static void lap_api_post_request_response_free(lap_api_post_request_response_t *response);
+
+static void lap_api_get_task_context_free(lap_api_get_request_context_t *context);
+static void lap_api_get_request_response_free(lap_api_get_request_response_t *response);
+static void lap_api_get_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable);
+static void lap_api_get_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data);
+
+#define G_ERROR_DOMAIN g_quark_from_static_string("cloud_lap_request")
+
+GCancellable *cloud_lap_request_api_racing_get(const char *ap_mac, cloud_request_lap_list_data_cb cb, void *user_data)
+{
+ GCancellable *cancellable = g_cancellable_new();
+
+ GTask *task = g_task_new(NULL, cancellable, lap_api_get_task_ready_cb, NULL);
+ g_task_set_source_tag(task, cloud_lap_request_api_racing_get);
+ g_task_set_return_on_cancel(task, FALSE);
+
+ lap_api_get_request_context_t *context = g_new0(lap_api_get_request_context_t, 1);
+ context->ap_mac = strndup(ap_mac, strlen(ap_mac));
+ context->cb = cb;
+ context->user_data = user_data;
+
+ g_task_set_task_data(task, context, (GDestroyNotify)lap_api_get_task_context_free);
+ g_task_run_in_thread(task, lap_api_get_task_thread_cb);
+
+ g_object_unref(task);
+
+ return cancellable;
+}
+
+GCancellable *cloud_lap_request_api_racing_post(const lap_info_t *lap_info, cloud_request_lap_post_finish_cb cb, void *user_data)
+{
+ GCancellable *cancellable = g_cancellable_new();
+
+ GTask *task = g_task_new(NULL, cancellable, lap_api_post_task_ready_cb, NULL);
+ g_task_set_source_tag(task, cloud_lap_request_api_racing_post);
+ g_task_set_return_on_cancel(task, FALSE);
+
+ lap_api_post_request_context_t *context = g_new0(lap_api_post_request_context_t, 1);
+ context->lap = lap_info_copy(lap_info);
+ context->cb = cb;
+ context->user_data = user_data;
+
+ g_task_set_task_data(task, context, (GDestroyNotify)lap_api_post_task_context_free);
+ g_task_run_in_thread(task, lap_api_post_task_thread_cb);
+
+ g_object_unref(task);
+
+ return cancellable;
+}
+
+static void lap_api_post_task_context_free(lap_api_post_request_context_t *context)
+{
+ ret_if(!context);
+
+ lap_info_destroy(context->lap);
+ g_free(context);
+}
+
+static void lap_api_post_request_response_free(lap_api_post_request_response_t *response)
+{
+ ret_if(!response);
+
+ g_free(response->response_msg);
+ g_free(response);
+}
+
+static void lap_api_post_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable)
+{
+ lap_api_post_request_context_t *context = (lap_api_post_request_context_t *)task_data;
+
+ if (g_task_return_error_if_cancelled(task)) {
+ return;
+ }
+
+ lap_api_post_request_response_t *response = g_new0(lap_api_post_request_response_t, 1);
+
+ char *json = lap_info_serializer_serialize(context->lap);
+ int retval = http_request_post(BASE_URL""PATH_API_LAP, json, &(response->response_msg), &(response->response_code));
+ g_free(json);
+
+ if (retval != 0) {
+ GError *err = g_error_new(G_ERROR_DOMAIN, retval, "http_request_post failed!");
+ g_task_return_error(task, err);
+ }
+
+ g_task_return_pointer(task, response, (GDestroyNotify)lap_api_post_request_response_free);
+}
+
+static void lap_api_post_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GTask *task = G_TASK(res);
+ GError *error = NULL;
+
+ //If no error occurred g_task_propagate_pointer transfers ownership, so later response have to be freed.
+ lap_api_post_request_response_t *response = g_task_propagate_pointer(task, &error);
+ if (error != NULL) {
+ _E("POST async task failed with msg: %s", error->message);
+ g_error_free(error);
+ return;
+ }
+ lap_api_post_request_context_t *context = g_task_get_task_data(task);
+
+ bool result = (response->response_code == 200 && (strncmp(response->response_msg, "Success", strlen("Success")) == 0)) ?
+ true :
+ false;
+
+ if (context->cb) {
+ context->cb(result, context->user_data);
+ }
+
+ lap_api_post_request_response_free(response);
+}
+
+static void lap_api_get_task_context_free(lap_api_get_request_context_t *context)
+{
+ ret_if(!context);
+
+ g_free(context->ap_mac);
+ g_free(context);
+}
+
+static void lap_api_get_request_response_free(lap_api_get_request_response_t *response)
+{
+ ret_if(!response);
+ ret_if(response->size <= 0);
+
+ for (int i = 0; i < response->size; i++)
+ {
+ lap_info_destroy(response->laps[i]);
+ }
+ g_free(response->laps);
+ g_free(response);
+}
+
+static void lap_api_get_task_thread_cb(GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable)
+{
+ lap_api_get_request_context_t *context = (lap_api_get_request_context_t *)task_data;
+
+ if (g_task_return_error_if_cancelled(task)) {
+ return;
+ }
+
+ lap_api_get_request_response_t *response = g_new0(lap_api_get_request_response_t, 1);
+ char *response_json = NULL;
+
+ GString *url = g_string_new(BASE_URL""PATH_API_LAP"?apMac=");
+ g_string_append(url, context->ap_mac);
+
+ int retval = http_request_get(url->str, &response_json, &(response->response_code));
+ g_string_free(url, TRUE);
+
+ if (retval != 0) {
+ GError *err = g_error_new(G_ERROR_DOMAIN, retval, "http_request_get failed!");
+ g_task_return_error(task, err);
+ }
+ else {
+ response->laps = lap_info_serializer_deserialize_array(response_json, &(response->size));
+ }
+
+ g_free(response_json);
+ g_task_return_pointer(task, response, (GDestroyNotify)lap_api_get_request_response_free);
+}
+
+static void lap_api_get_task_ready_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GTask *task = G_TASK(res);
+ GError *error = NULL;
+
+ //If no error occurred g_task_propagate_pointer transfers ownership, so later response have to be freed.
+ lap_api_get_request_response_t *response = g_task_propagate_pointer(task, &error);
+ if (error != NULL) {
+ _E("GET async task failed with msg: %s", error->message);
+ g_error_free(error);
+ return;
+ }
+ lap_api_get_request_context_t *context = g_task_get_task_data(task);
+
+ bool result = (response->response_code == 200) ? true : false;
+
+ if (context->cb) {
+ context->cb(result, response->laps, response->size, context->user_data);
+ }
+
+ lap_api_get_request_response_free(response);
+}