Fix a crash
[framework/location/libdecarta.git] / location_module / location_decarta.c
1 /*
2  * libdecarta
3  *
4  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
7  *          Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #include <glib.h>
23 #include <glib/gprintf.h>
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <vconf.h>
30 #include <location-module.h>
31 #include <location-poi.h>
32 #include <decarta.h>
33 #include <decarta_log.h>
34 #include <location.h>
35 #include <location-map-service.h>
36 #include <location-map-service-ext.h>
37 #include <decarta_config.h>
38
39 #include "location_decarta.h"
40
41 static char* service_name = "decarta";
42 GSList * async_request_queue;
43
44 int g_capa_list[] = {
45         TRUE,   //MAP_SERVICE_PREF_LANGUAGE
46         TRUE,   //MAP_SERVICE_PREF_DISTANCE_UNIT
47
48         TRUE,   //MAP_SERVICE_PREF_PROPERTY
49
50         TRUE,   //MAP_SERVICE_GEOCODE_TYPE
51         TRUE,   //MAP_SERVICE_REVERSE_GEOCODE_TYPE
52
53         TRUE,   //MAP_SERVICE_POI_TYPE
54         TRUE,   //MAP_SERVICE_POI_SEARCH_BY_ADDRESS
55         TRUE,   //MAP_SERVICE_POI_SEARCH_BY_FREEFORM_ADDRESS
56         TRUE,   //MAP_SERVICE_POI_SEARCH_BY_CIRCLE_BOUNDARY
57         FALSE,  //MAP_SERVICE_POI_SEARCH_BY_RECT_BOUNDARY
58         FALSE,  //MAP_SERVICE_POI_SEARCH_BY_POLYGON_BOUNDARY
59         TRUE,   //MAP_SERVICE_POI_PREF_SORT_BY
60         TRUE,   //MAP_SERVICE_POI_PREF_PROPERTY
61         TRUE,   //MAP_SERVICE_POI_FILTER,
62         TRUE,   //MAP_SERVICE_POI_FILTER_CATEGORY
63
64         TRUE,   //MAP_SERVICE_ROUTE_REQUEST_FREEFORM_ADDR_TO_AVOID
65         TRUE,   //MAP_SERVICE_ROUTE_REQUEST_STRUCTED_ADDR_TO_AVOID
66         TRUE,   //MAP_SERVICE_ROUTE_REQUEST_CIRCLE_AREA_TO_AVOID
67         FALSE,  //MAP_SERVICE_ROUTE_REQUEST_RECT_AREA_TO_AVOID
68         FALSE,  //MAP_SERVICE_ROUTE_REQUEST_POLYGON_AREA_TO_AVOID
69         TRUE,   //MAP_SERVICE_ROUTE_REQUEST_FEATURE_TO_AVOID
70         TRUE,   //MAP_SERVICE_ROUTE_PREF_TYPE
71         TRUE,   //MAP_SERVICE_ROUTE_PREF_TRANSPORT_MODE
72         TRUE,   //MAP_SERVICE_ROUTE_PREF_GEOMETRY_BOUNDING_BOX
73         TRUE,   //MAP_SERVICE_ROUTE_PREF_GEOMETRY_RETRIEVAL
74         TRUE,   //MAP_SERVICE_ROUTE_PREF_INSTRUCTION_GEOMETRY
75         TRUE,   //MAP_SERVICE_ROUTE_PREF_INSTRUCTION_BOUNDING_BOX
76         TRUE,   //MAP_SERVICE_ROUTE_PREF_INSTRUCTION_RETRIEVAL
77         TRUE,   //MAP_SERVICE_ROUTE_PREF_REALTIME_TRAFFIC
78         FALSE,  //MAP_SERVICE_ROUTE_PREF_PROPERTY
79         TRUE,   //MAP_SERVICE_ROUTE_DISTANCE_UNIT
80         FALSE,  //MAP_SERVICE_ROUTE_PROPERTY
81         FALSE,  //MAP_SERVICE_ROUTE_SEGMENT_PROPERTY
82         FALSE   //MAP_SERVICE_ROUTE_STEP_PROPERTY
83 };
84
85 static void
86 __pos_list_item_free(gpointer data)
87 {
88         g_return_if_fail(data);
89         LocationPosition *position = (LocationPosition *)data;
90         location_position_free(position);
91 }
92
93 static void
94 decarta_position_free_list(GList *position_list)
95 {
96         g_return_if_fail(position_list);
97         g_list_free_full(position_list, (GDestroyNotify)__pos_list_item_free);
98 }
99
100 static void
101 __acc_list_item_free(gpointer data)
102 {
103         g_return_if_fail(data);
104         LocationAccuracy *accuracy = (LocationAccuracy *)data;
105         location_accuracy_free(accuracy);
106 }
107
108 static void
109 decarta_accuracy_free_list(GList *accuracy_list)
110 {
111         g_return_if_fail(accuracy_list);
112         g_list_free_full(accuracy_list, (GDestroyNotify)__acc_list_item_free);
113 }
114
115 static int
116 convert_decarta_error_to_location_error (int err)
117 {
118         switch (err) {
119         case DECARTA_ERROR_NONE:
120                 return LOCATION_ERROR_NONE;
121         case DECARTA_ERROR_CONFIGURATION_FILE:
122                 return LOCATION_ERROR_CONFIGURATION;
123         case DECARTA_ERROR_HTTP:
124                 return LOCATION_ERROR_NETWORK_FAILED;
125         case DECARTA_ERROR_NOT_FOUND:
126                 return LOCATION_ERROR_NOT_FOUND;
127         case DECARTA_ERROR_XML:
128         default:
129                 return LOCATION_ERROR_UNKNOWN;
130         }
131 }
132
133 static DecartaFormedAddress*
134 get_decarta_addr_from_location_addr (const LocationAddress *address)
135 {
136         if (!address) return NULL;
137         return decarta_formed_address_new (address->building_number,
138                                                                         address->street,
139                                                                         address->state, NULL,
140                                                                         address->city,
141                                                                         address->district,
142                                                                         address->postal_code, NULL, NULL);
143 }
144
145 static LocationAddress *
146 get_location_addr_from_decarta_addr (const DecartaAddress *deca_addr)
147 {
148         if (!deca_addr) return NULL;
149         LocationAddress* addr = NULL;
150         if (deca_addr->is_freerorm) {
151                 //FIXME: how to convert free to formed...??
152                 addr = location_address_new (NULL, NULL, NULL, NULL, NULL, NULL, NULL);
153         } else if (deca_addr->formed_addr) {
154                 addr = location_address_new (deca_addr->formed_addr->street_number,
155                                                                 deca_addr->formed_addr->street_name,
156                                                                 deca_addr->formed_addr->district,
157                                                                 deca_addr->formed_addr->city,
158                                                                 deca_addr->formed_addr->state,
159                                                                 deca_addr->country_code,
160                                                                 deca_addr->formed_addr->postal_code);
161         }
162         return addr;
163 }
164
165 static LocationPosition *
166 get_location_pos_from_decarta_pos (const DecartaPosition *deca_pos)
167 {
168         if (!deca_pos) return NULL;
169         return location_position_new (0, deca_pos->latitude, deca_pos->longitude, 0, LOCATION_STATUS_2D_FIX);
170 }
171
172 static LocationAccuracy *
173 get_location_acc_from_free_addr (const char *free_addr)
174 {
175         if (!free_addr) return NULL;
176         //FIXME: how to convert free to formed...??
177         return location_accuracy_new (LOCATION_ACCURACY_LEVEL_POSTALCODE, 0, 0);
178 }
179
180 static LocationAccuracy *
181 get_location_acc_from_location_addr (const LocationAddress *addr)
182 {
183         if (!addr) return NULL;
184         LocationAccuracy *accuracy = NULL;
185
186         if (addr->building_number)   accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_DETAILED, 0, 0);
187         else if (addr->street)       accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_STREET, 0, 0);
188         else if (addr->postal_code)  accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_POSTALCODE, 0, 0);
189         else if (addr->district ||
190                         addr->city)          accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_LOCALITY, 0, 0);
191         else if (addr->state)        accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_REGION, 0, 0);
192         else if (addr->country_code) accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_COUNTRY, 0, 0);
193         else                         accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0, 0);
194
195         return accuracy;
196 }
197
198 static LocationAccuracy *
199 get_location_acc_from_decarta_addr (const DecartaAddress *addr)
200 {
201         if (!addr) return NULL;
202         LocationAccuracy *accuracy = NULL;
203         if (addr->is_freerorm && addr->freeform_address) {
204                 //FIXME: how to convert free to formed...??
205                 accuracy = get_location_acc_from_free_addr(addr->freeform_address);
206         } else if (addr->formed_addr) {
207                 DecartaFormedAddress *formed_addr = addr->formed_addr;
208                 if (formed_addr->street_number)       accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_DETAILED, 0, 0);
209                 else if (formed_addr->street_number)  accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_STREET, 0, 0);
210                 else if (formed_addr->postal_code)    accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_POSTALCODE, 0, 0);
211                 else if (formed_addr->district ||
212                                 formed_addr->city)            accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_LOCALITY, 0, 0);
213                 else if (formed_addr->state)          accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_REGION, 0, 0);
214                 else if (addr->country_code)          accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_COUNTRY, 0, 0);
215                 else                                  accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0, 0);
216         }
217         return accuracy;
218 }
219
220
221
222 static void
223 get_lang (gchar country_code[3], gchar lang_code[3])
224 {
225         if (!country_code || !lang_code) return;
226         gchar* langset = vconf_get_str(VCONFKEY_LANGSET);
227         DECARTA_LOGD("getenv: %s", langset);
228
229         if(langset == NULL){
230                 lang_code[0] = 'E';
231                 lang_code[1] = 'N';
232                 lang_code[2] = '\0';
233                 country_code[0] = 'U';
234                 country_code[1] = 'S';
235                 country_code[2] = '\0';
236         }else{
237                 gchar* langset_upper = g_ascii_strup(langset, -1);
238                 lang_code[0] = langset_upper[0];
239                 lang_code[1] = langset_upper[1];
240                 lang_code[2] = '\0';
241                 country_code[0] = langset_upper[3];
242                 country_code[1] = langset_upper[4];
243                 country_code[2] = '\0';
244                 g_free(langset_upper);
245         }
246         DECARTA_LOGD("Language: %s, Country: %s", lang_code, country_code);
247 }
248
249 static int
250 get_service_name (gpointer handle,
251         gchar **_service_name)
252 {
253         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
254         g_return_val_if_fail(_service_name, LOCATION_ERROR_PARAMETER);
255         *_service_name = g_strdup(service_name);
256         return LOCATION_ERROR_NONE;
257 }
258
259 static void
260 address_cb (DecartaError deca_err,
261         const DecartaGeocode *geocode,
262         void *userdata)
263 {
264         LocationAddress *addr = NULL;
265         LocationAccuracy *acc = NULL;
266         LocationError error = LOCATION_ERROR_NONE;
267         DecartaData* data = (DecartaData*)userdata;
268         g_return_if_fail(data);
269
270         async_request_queue = g_slist_remove(async_request_queue , data->handle);
271
272         if (deca_err == DECARTA_ERROR_NONE && geocode && geocode->addr) {
273                 DECARTA_LOGD("address_cb: success");
274                 addr = get_location_addr_from_decarta_addr (geocode->addr);
275                 acc = get_location_acc_from_decarta_addr (geocode->addr);
276         } else {
277                 DECARTA_LOGD("address_cb: failed");
278                 error = convert_decarta_error_to_location_error (deca_err);
279         }
280         if (data->addr_cb) data->addr_cb (error, addr, acc, data->userdata);
281         if (addr) location_address_free (addr);
282         if (acc) location_accuracy_free (acc);
283         g_free (data);
284 }
285
286 static void
287 position_cb (DecartaError deca_err,
288         const GList *geocode_list,
289         void *userdata)
290 {
291         LocationPosition *pos = NULL;
292         LocationAccuracy *acc = NULL;
293         GList *position_list = NULL;
294         GList *accuracy_list = NULL;
295         LocationError error = LOCATION_ERROR_NONE;
296         DecartaData* data = (DecartaData*)userdata;
297         g_return_if_fail(data);
298
299         int i = 1;
300
301         async_request_queue = g_slist_remove(async_request_queue , data->handle);
302
303         if (deca_err == DECARTA_ERROR_NONE) {
304                 DECARTA_LOGD("position_cb: success");
305
306                 // get rid of const
307                 GList *tmp_geocode_list = (GList *)geocode_list;
308
309                 const DecartaGeocode *geocode = NULL;
310                 tmp_geocode_list = decarta_geocode_list_next(tmp_geocode_list, &geocode);
311
312                 if (geocode) {
313                         while (geocode) {
314                                 // Fixme: geocode->pos NULL case ?
315                                 pos = get_location_pos_from_decarta_pos (geocode->pos);
316                                 acc = location_accuracy_copy ((LocationAccuracy *)(data->userdata2));
317
318                                 if (!pos) {
319                                         if (acc) {
320                                                 location_accuracy_free(acc);
321                                                 acc = NULL;
322                                         }
323                                         continue;
324                                 }
325                                 DECARTA_LOGD("location decarta plugin: position_cb %d, lat %f, lon %f ", i++, pos->latitude, pos->longitude);
326
327                                 position_list = g_list_append (position_list, (gpointer)pos);
328                                 accuracy_list = g_list_append (accuracy_list, (gpointer)acc);
329
330                                 if (!tmp_geocode_list) break;
331                                 tmp_geocode_list = decarta_geocode_list_next(tmp_geocode_list, &geocode);
332                         }
333                 } else {
334                         error = LOCATION_ERROR_NOT_FOUND;
335                 }
336         } else {
337                 DECARTA_LOGD("position_cb: failed");
338                 error = convert_decarta_error_to_location_error (deca_err);
339         }
340         if (data->pos_cb) {
341                 if (position_list == NULL) error = LOCATION_ERROR_NOT_FOUND;
342                 data->pos_cb(error, position_list, accuracy_list, data->userdata);
343         }
344
345         if(position_list) decarta_position_free_list(position_list);
346         if(accuracy_list) decarta_accuracy_free_list(accuracy_list);
347
348         location_accuracy_free ((LocationAccuracy *)data->userdata2);
349         g_free (data);
350 }
351
352 static void
353 __decarta_append_landmark_list (gpointer data,
354         gpointer user_data)
355 {
356         DecartaPOI *poi = (DecartaPOI *)data;
357         GList **landmark_list = (GList **)user_data;
358         LocationPosition *loc_position = NULL;
359         LocationAddress *loc_address = NULL;
360
361         LocationLandmark *landmark = location_landmark_new();
362
363         DECARTA_LOGD("name:%s id:%s phone_number:%s\n", poi->name, poi->id, poi->phone_number);
364         guint id_uint = g_ascii_strtoull(poi->id, NULL, 10);
365         location_landmark_set_id(landmark, id_uint);
366         location_landmark_set_name(landmark, poi->name);
367         location_landmark_set_phone_number(landmark, poi->phone_number);
368
369         char *key = NULL;
370         char *value = NULL;
371         decarta_poi_info_table_iter_init (poi->info_list);
372         while (decarta_poi_info_list_table_next (poi->info_list, &key, &value))
373         {
374                 DECARTA_LOGD("%s=%s\n", key, value);
375                 location_landmark_set_property(landmark, key, value);
376         }
377         if(poi->pos) {
378                 DECARTA_LOGD("Position: %lf %lf\n", poi->pos->latitude, poi->pos->longitude);
379                 loc_position = get_location_pos_from_decarta_pos (poi->pos);
380                 location_landmark_set_position(landmark, loc_position);
381         }
382         if (poi->addr) {
383                 loc_address = get_location_addr_from_decarta_addr (poi->addr);
384                 location_landmark_set_address(landmark, loc_address);
385         }
386
387         *landmark_list = g_list_append(*landmark_list, landmark);
388
389 }
390
391 static void
392 __decarta_free_landmark_list (gpointer data,
393         gpointer user_data)
394 {
395         LocationLandmark* landmark = (LocationLandmark*)data;
396         location_landmark_free(landmark);
397 }
398
399 static void
400 decarta_landmark_free_list(GList *landmark_list)
401 {
402         g_return_if_fail(landmark_list);
403         g_list_foreach(landmark_list, (GFunc)__decarta_free_landmark_list, NULL);
404         g_list_free(landmark_list);
405         landmark_list = NULL;
406 }
407
408
409 static
410 void landmark_cb (DecartaError error,
411         const gchar *req_id_str,
412         const GList* poi_list,
413         const gchar *error_code,
414         const gchar *error_msg,
415         void *userdata)
416 {
417         LocationError loc_error = LOCATION_ERROR_NONE;
418         DecartaData* data = (DecartaData*)userdata;
419         g_return_if_fail(data);
420         guint req_id = 0;
421         GList *landmark_list = NULL;
422
423         if (error == DECARTA_ERROR_NONE) {
424                 DECARTA_LOGD("landmark_cb: success, req_id %s", req_id_str);
425
426                 GList *tmp_poi_list = (GList *)poi_list;
427                 g_list_foreach(tmp_poi_list, (GFunc)__decarta_append_landmark_list, &landmark_list);
428         } else {
429                 DECARTA_LOGD("landmark_cb: failed, req_id %s, error code %s, msg %s", req_id_str, error_code, error_msg);
430
431                 loc_error = convert_decarta_error_to_location_error (error);
432         }
433         if (data->poi_cb) {
434                 req_id = g_ascii_strtoull(req_id_str, NULL, 10);
435                 gchar *code = g_strdup(error_code);
436                 gchar *msg = g_strdup(error_msg);
437                 data->poi_cb(loc_error, req_id, landmark_list, code, msg, data->userdata);
438                 g_free(code);
439                 g_free(msg);
440         }
441         if (landmark_list) decarta_landmark_free_list(landmark_list);
442
443         g_free(data);
444 }
445
446 // used to split the step into segments
447 static DecartaBoundary *
448 __decarta_route_boundary_new_for_rect (DecartaPosition* left_top,
449         DecartaPosition* right_bottom)
450 {
451         g_return_val_if_fail(left_top, NULL);
452         g_return_val_if_fail(right_bottom, NULL);
453
454         DecartaBoundary* boundary = g_slice_new0 (DecartaBoundary);
455         boundary->type = DECARTA_BOUNDARY_RECT;
456         boundary->rect.left_top = decarta_position_copy(left_top);
457         boundary->rect.right_bottom = decarta_position_copy(right_bottom);
458         return boundary;
459 }
460
461 // postion's latitude & longitude between the boundary
462 static gboolean
463 __decarta_route_boundary_if_inside (DecartaBoundary* boundary,
464         const DecartaPosition* position)
465 {
466         g_return_val_if_fail(boundary, FALSE);
467         g_return_val_if_fail(position, FALSE);
468
469         gboolean is_inside = FALSE;
470
471         switch(boundary->type) {
472
473                 case DECARTA_BOUNDARY_RECT: {
474                         gdouble y = position->latitude;
475                         gdouble x = position->longitude;
476                         gdouble y_min, y_max;
477                         gdouble x_min, x_max;
478
479                         if (boundary->rect.left_top->latitude < boundary->rect.right_bottom->latitude) {
480                                 y_min = boundary->rect.left_top->latitude;
481                                 y_max = boundary->rect.right_bottom->latitude;
482                         } else {
483                                 y_max = boundary->rect.left_top->latitude;
484                                 y_min = boundary->rect.right_bottom->latitude;
485                         }
486
487                         if (boundary->rect.left_top->longitude < boundary->rect.right_bottom->longitude) {
488                                 x_min = boundary->rect.left_top->longitude;
489                                 x_max = boundary->rect.right_bottom->longitude;
490                         } else {
491                                 x_max = boundary->rect.left_top->longitude;
492                                 x_min = boundary->rect.right_bottom->longitude;
493                         }
494
495                         if (x > x_min && x < x_max && y > y_min && y < y_max) {
496                                 DECARTA_LOGD("\tInside of Rectangular boundary");
497                                 is_inside = TRUE;
498                         }
499
500                         break;
501                 }
502                 case DECARTA_BOUNDARY_CIRCLE: {
503                         DECARTA_LOGW("\tCircle boundary type is TBD.");
504                         // TBD
505                         break;
506                 }
507                 case DECARTA_BOUNDARY_POLYGON: {
508                         DECARTA_LOGW("\tPolygon boundary type is TBD.");
509                         // TBD
510                         break;
511                 }
512                 default: {
513                         DECARTA_LOGW("\tboundary type is undefined.[%d]", boundary->type);
514                         break;
515                 }
516         }
517
518         return is_inside;
519 }
520
521
522 static void
523 __route_step_foreach_free (gpointer data)
524 {
525         g_return_if_fail (data);
526         LocationRouteStep *step = (LocationRouteStep *) data;
527         location_route_step_free(step);
528 }
529
530 static void
531 __route_segment_foreach_free (gpointer data)
532 {
533         g_return_if_fail (data);
534         LocationRouteSegment *segment = (LocationRouteSegment *)data;
535         location_route_segment_free(segment);
536 }
537
538 static LocationBoundary *
539 get_location_boundary_from_decarta_bbox(LocationPosition *pos1,
540         LocationPosition *pos2)
541 {
542         g_return_val_if_fail(pos1, NULL);
543         g_return_val_if_fail(pos2, NULL);
544         LocationPosition *right_bottom = NULL;
545         LocationPosition *left_top = NULL;
546
547         // determine the right_bottom & left_top postion
548         gdouble lon_interval = pos2->longitude - pos1->longitude;
549         if(lon_interval < 180 && lon_interval > -180) {
550                 if(pos2->longitude <= pos1->longitude || pos2->latitude >= pos1->latitude) {
551                         right_bottom = pos1;
552                         left_top = pos2;
553                 } else {
554                         right_bottom = pos2;
555                         left_top = pos1;
556                 }
557         }
558         else {
559                 if(pos2->longitude >= pos1->longitude || pos2->latitude >= pos1->latitude) {
560                         right_bottom = pos1;
561                         left_top = pos2;
562                 } else {
563                         right_bottom = pos2;
564                         left_top = pos1;
565                 }
566         }
567
568         LocationBoundary *bbox = location_boundary_new_for_rect(left_top, right_bottom);
569         if (!bbox) {
570                 g_printf("ERROR: get_location_boundary_from_decarta_bbox failed\n");
571                 return NULL;
572         } else {
573                 return bbox;
574         }
575 }
576
577 static GList *
578 get_location_route_list_from_decarta_route (const DecartaRoute *route,
579         const LocationPosition *origin,
580         const LocationPosition *destination)
581 {
582         GList *route_list = NULL;
583         LocationRoute *loc_route = location_route_new();
584         GList *seg_list = NULL;
585         GList *step_list = NULL;
586
587         // set the route origin & destination
588         location_route_set_origin(loc_route, origin);
589         location_route_set_destination(loc_route, destination);
590
591         // set the duration, distance
592         location_route_set_total_distance(loc_route, route->total_distance);
593         location_route_set_distance_unit(loc_route, "M");
594         location_route_set_total_duration(loc_route, route->total_time);
595
596         // set the rout rect area
597         LocationPosition *pos1 = get_location_pos_from_decarta_pos(route->box_corner1);
598         LocationPosition *pos2 = get_location_pos_from_decarta_pos(route->box_corner2);
599         // Fixme: can't create the boundary?
600         LocationBoundary *bbox = get_location_boundary_from_decarta_bbox(pos1, pos2);
601         location_position_free(pos1);
602         location_position_free(pos2);
603         location_route_set_bounding_box(loc_route, bbox);
604
605         //set the segments for route
606         if (route->instructions_list) {
607                 GList *inst_list = (GList *)route->instructions_list;
608                 const DecartaRouteInstructions *inst = NULL;
609                 inst_list = decarta_route_instructions_list_next( inst_list, &inst);
610
611                 GList *pos_list = (GList *)route->line_pos_list;
612                 DecartaPosition *pos_prev = NULL;
613                 // for each instruction
614                 while (inst) {
615                         LocationRouteSegment *seg = location_route_segment_new();
616                         location_route_segment_set_distance(seg, inst->distance);
617                         location_route_segment_set_duration(seg, inst->duration);
618
619                         if (step_list) {
620                                 g_list_free_full (step_list, __route_step_foreach_free);
621                                 step_list = NULL;
622                         }
623
624                         DecartaBoundary *instuct_rect = __decarta_route_boundary_new_for_rect(inst->map->box_corner1, inst->map->box_corner2);
625
626                         if (pos_list) {
627                                 const DecartaPosition *pos = NULL;
628                                 pos_list = decarta_position_list_next(pos_list, &pos);
629                                 while (pos) {
630                                         // search the whole pos list for each instruction
631                                         if (__decarta_route_boundary_if_inside(instuct_rect, pos)) {
632                                                 LocationRouteStep *step = location_route_step_new();
633                                                 if (pos_prev) {
634                                                         location_route_step_set_start_point(step, get_location_pos_from_decarta_pos(pos_prev));
635
636                                                         // set geometry for location step
637                                                         GList *geometry_list = NULL;
638                                                         geometry_list = g_list_append(geometry_list, get_location_pos_from_decarta_pos(pos_prev));
639                                                         geometry_list = g_list_append(geometry_list, get_location_pos_from_decarta_pos(pos));
640                                                         location_route_step_set_geometry(step, geometry_list);
641
642                                                         decarta_position_free(pos_prev);
643                                                         pos_prev = NULL;
644                                                 } else {
645                                                         // the first segment's first position should be Origin
646                                                         location_route_step_set_start_point(step, origin);
647                                                 }
648                                                 location_route_step_set_instruction(step, inst->instruction);
649                                                 location_route_step_set_end_point(step, get_location_pos_from_decarta_pos(pos));
650
651                                                 step_list = g_list_append(step_list, step);
652                                                 pos_prev = decarta_position_copy(pos);
653                                         }
654
655                                         if (!pos_list) break;
656                                         pos_list = decarta_position_list_next(pos_list, &pos);
657
658                                 }
659
660                                 // search from beginning of the pos list
661                                 pos_list = (GList *)route->line_pos_list;
662                         }
663
664                         if (step_list) {
665                                 location_route_segment_set_route_step(seg, step_list);
666                                 GList *seg_first = g_list_first(step_list);
667                                 if (seg_first) {
668                                         LocationRouteStep *seg_first_step = (LocationRouteStep *)seg_first->data;
669                                         const LocationPosition *seg_start_pos = location_route_step_get_start_point(seg_first_step);
670                                         location_route_segment_set_start_point(seg, seg_start_pos);
671                                 }
672                                 GList *seg_last = g_list_last(step_list);
673                                 if (seg_last) {
674                                         LocationRouteStep *seg_last_step = (LocationRouteStep *)seg_last->data;
675                                         const LocationPosition *seg_end_pos = location_route_step_get_end_point(seg_last_step);
676                                         location_route_segment_set_end_point(seg, seg_end_pos);
677                                 }
678                         }
679
680                         seg_list = g_list_append(seg_list, seg);
681
682                         if (!inst_list) break;
683                         inst_list = decarta_route_instructions_list_next (inst_list, &inst);
684                 }
685         }
686
687         if (seg_list) {
688                 location_route_set_route_segment(loc_route, seg_list);
689                 g_list_free_full (seg_list, __route_segment_foreach_free);
690                 seg_list = NULL;
691         }
692
693         route_list = g_list_append(route_list, loc_route);
694         return route_list;
695 }
696
697
698 static void
699 __decarta_free_route_list (gpointer data,
700         gpointer user_data)
701 {
702         LocationRoute *route = (LocationRoute *)data;
703         GList *seg_list = (GList *)location_route_get_route_segment(route);
704         if (seg_list) {
705                 g_list_foreach(seg_list, (GFunc)__route_segment_foreach_free, NULL);
706         }
707 }
708
709 static void
710 decarta_route_free_list(GList *route_list)
711 {
712         g_return_if_fail(route_list);
713         g_list_foreach(route_list, (GFunc)__decarta_free_route_list, NULL);
714         g_list_free(route_list);
715         route_list = NULL;
716 }
717
718
719 void route_callback(DecartaError error,
720         const gchar *req_id_str,
721         const DecartaRoute *route,
722         const gchar * error_code,
723         const gchar * error_msg,
724         void *user_data)
725 {
726         LocationError loc_error = LOCATION_ERROR_NONE;
727         DecartaData* data = (DecartaData*)user_data;
728         g_return_if_fail(data);
729         guint req_id = 0;
730         GList *route_list = NULL;
731         LocationPosition *origin = (LocationPosition *)data->userdata2;
732         LocationPosition *destination = (LocationPosition *)data->userdata3;
733
734         if (error == DECARTA_ERROR_NONE) {
735                 DECARTA_LOGD("route_callback: success");
736                 route_list = get_location_route_list_from_decarta_route(route, origin, destination);
737
738         } else {
739                 DECARTA_LOGD("route_callback: failed");
740                 loc_error = convert_decarta_error_to_location_error (error);
741         }
742         if (data->route_cb) {
743                 gchar *code = g_strdup(error_code);
744                 gchar *msg = g_strdup(error_msg);
745                 data->route_cb(loc_error, req_id, route_list, code, msg, data->userdata);
746                 g_free(code);
747                 g_free(msg);
748         }
749         if (route_list) decarta_route_free_list(route_list);
750         if (origin) location_position_free(origin);
751         if (destination) location_position_free(destination);
752         g_free(data);
753 }
754
755 static int
756 get_geocode (gpointer handle,
757         const LocationAddress *addr,
758         const LocationMapPref *svc_pref,
759         GList **position_list,
760         GList **accuracy_list)
761 {
762         DECARTA_LOGD("get_geocode");
763         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
764         g_return_val_if_fail (addr, LOCATION_ERROR_PARAMETER);
765         g_return_val_if_fail (position_list, LOCATION_ERROR_PARAMETER);
766         g_return_val_if_fail (accuracy_list, LOCATION_ERROR_PARAMETER);
767
768         int i = 1;
769         GList *geocode_list = NULL;
770         LocationPosition *pos = NULL;
771         LocationAccuracy *acc = NULL;
772
773         char *ID = NULL;
774         char *password = NULL;
775         ID = location_map_pref_get_property(svc_pref, "ID");
776         password = location_map_pref_get_property(svc_pref, "PASSWORD");
777         set_config(ID, password, NULL, NULL);
778
779         char *language_code = NULL;
780         char *country_code = NULL;
781         language_code = location_map_pref_get_language(svc_pref);
782         country_code = location_map_pref_get_country(svc_pref);
783         if (language_code == NULL || country_code == NULL) {
784                 gchar tmp_country[3] = "";
785                 gchar tmp_language[3] = "";
786                 get_lang(tmp_country, tmp_language);
787                 if (country_code == NULL) {
788                         country_code = g_strdup(tmp_country);
789                 }
790                 if (language_code == NULL) {
791                         language_code = g_strdup(tmp_language);
792                 }
793         }
794
795         DecartaFormedAddress *deca_formed_addr = get_decarta_addr_from_location_addr (addr);
796         DecartaAddress *deca_addr = decarta_address_new (country_code, language_code, FALSE, NULL, deca_formed_addr);
797         decarta_formed_address_free (deca_formed_addr);
798         int ret = decarta_search_geocode(deca_addr, &geocode_list);
799         decarta_address_free (deca_addr);
800
801         if (ret == DECARTA_ERROR_NONE) {
802                 // libslp-location getting multi addresses.
803                 /* can't change the geocode_list for del */
804                 GList *tmp_geocode_list = (GList *)geocode_list;
805                 const DecartaGeocode *geocode = NULL;
806                 tmp_geocode_list = decarta_geocode_list_next(tmp_geocode_list, &geocode);
807
808                 while (geocode) {
809                         pos = get_location_pos_from_decarta_pos (geocode->pos);
810                         acc = get_location_acc_from_location_addr (addr);
811
812                         DECARTA_LOGD("location decarta plugin: get_geocode %d, lat %f, lon %f ", i++, pos->latitude, pos->longitude);
813
814                         *position_list = g_list_append (*position_list, (gpointer)pos);
815                         *accuracy_list = g_list_append (*accuracy_list, (gpointer)acc);
816
817                         if (!tmp_geocode_list) break;
818                         tmp_geocode_list = decarta_geocode_list_next(tmp_geocode_list, &geocode);
819                 }
820                 decarta_geocode_list_free (geocode_list);
821         }
822         return convert_decarta_error_to_location_error (ret);
823 }
824
825 static gboolean
826 decarta_idle_geocode_cb (gpointer data)
827 {
828         decarta_IdleData* idle_data = (decarta_IdleData*)data;
829         if (idle_data == NULL || idle_data->decarta_data == NULL) {
830                 g_printf("idle_data or decarta_data is NULL\n");
831                 return FALSE;
832         }
833
834         DecartaData *deca_data = (DecartaData *)idle_data->decarta_data;
835         int err = decarta_search_geocode_async(idle_data->addr, idle_data->geocode_cb, deca_data, &deca_data->handle);
836         async_request_queue  = g_slist_prepend(async_request_queue , deca_data->handle);
837         if (DECARTA_ERROR_NONE != err) {
838                 g_printf("Decarta Geocode Failed: %d\n", err);
839
840                 // call position_cb() to return the error code, and free DecartaData
841                 if (idle_data->geocode_cb) {
842                         idle_data->geocode_cb (err, NULL, idle_data->decarta_data);
843                 }
844         }
845         decarta_address_free (idle_data->addr);
846         g_free(idle_data);
847         return FALSE;
848 }
849
850
851 static int
852 get_geocode_async (gpointer handle,
853         const LocationAddress * addr,
854         const LocationMapPref *svc_pref,
855         LocationPositionCB callback,
856         gpointer userdata)
857 {
858         DECARTA_LOGD("get_geocode_async");
859         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
860         g_return_val_if_fail (addr, LOCATION_ERROR_PARAMETER);
861         g_return_val_if_fail (callback, LOCATION_ERROR_PARAMETER);
862
863         char *ID = NULL;
864         char *password = NULL;
865         ID = location_map_pref_get_property(svc_pref, "ID");
866         password = location_map_pref_get_property(svc_pref, "PASSWORD");
867         set_config(ID, password, NULL, NULL);
868
869         DecartaData* data = g_new0(DecartaData, 1);
870
871         char *language_code = NULL;
872         char *country_code = NULL;
873         language_code = location_map_pref_get_language(svc_pref);
874         country_code = location_map_pref_get_country(svc_pref);
875         if (language_code == NULL || country_code == NULL) {
876                 gchar tmp_country[3] = "";
877                 gchar tmp_language[3] = "";
878                 get_lang(tmp_country, tmp_language);
879                 if (country_code == NULL) {
880                         country_code = g_strdup(tmp_country);
881                 }
882                 if (language_code == NULL) {
883                         language_code = g_strdup(tmp_language);
884                 }
885         }
886
887         DecartaFormedAddress *deca_formed_addr = get_decarta_addr_from_location_addr (addr);
888         DecartaAddress *deca_addr = decarta_address_new (country_code, language_code, FALSE, NULL, deca_formed_addr);
889         decarta_formed_address_free (deca_formed_addr);
890         data->pos_cb = callback;
891         data->userdata = (gpointer)userdata;
892         data->userdata2 = (gpointer)get_location_acc_from_decarta_addr (deca_addr);
893
894         // should call decarta_search_geocode_async in idle, OR request may be missed
895         decarta_IdleData* idle_data= g_new0 (decarta_IdleData, 1);
896         idle_data->addr = deca_addr;
897         idle_data->geocode_cb = position_cb;
898         idle_data->decarta_data = data;
899         g_idle_add((GSourceFunc)decarta_idle_geocode_cb, (gpointer)idle_data);
900
901         return LOCATION_ERROR_NONE;
902 }
903
904 static int
905 get_geocode_freetext(gpointer handle,
906         const gchar* addr,
907         const LocationMapPref *svc_pref,
908         GList **position_list,
909         GList **accuracy_list)
910 {
911         DECARTA_LOGD ("get_geocode_freetext");
912         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
913         g_return_val_if_fail (addr, LOCATION_ERROR_PARAMETER);
914         g_return_val_if_fail (position_list, LOCATION_ERROR_PARAMETER);
915         g_return_val_if_fail (accuracy_list, LOCATION_ERROR_PARAMETER);
916
917         int i = 1;
918         GList *geocode_list = NULL;
919         LocationPosition *pos = NULL;
920         LocationAccuracy *acc = NULL;
921
922         char *ID = NULL;
923         char *password = NULL;
924         ID = location_map_pref_get_property(svc_pref, "ID");
925         password = location_map_pref_get_property(svc_pref, "PASSWORD");
926         set_config(ID, password, NULL, NULL);
927
928         char *language_code = NULL;
929         char *country_code = NULL;
930         language_code = location_map_pref_get_language(svc_pref);
931         country_code = location_map_pref_get_country(svc_pref);
932         if (language_code == NULL || country_code == NULL) {
933                 gchar tmp_country[3] = "";
934                 gchar tmp_language[3] = "";
935                 get_lang(tmp_country, tmp_language);
936                 if (country_code == NULL) {
937                         country_code = g_strdup(tmp_country);
938                 }
939                 if (language_code == NULL) {
940                         language_code = g_strdup(tmp_language);
941                 }
942         }
943
944         DecartaAddress *deca_addr = decarta_address_new (country_code, language_code, TRUE, addr, NULL);
945         int ret = decarta_search_geocode(deca_addr, &geocode_list);
946         decarta_address_free (deca_addr);
947
948         if (ret == DECARTA_ERROR_NONE) {
949                 // libslp-location getting multi addresses.
950                 /* can't change the geocode_list for del */
951                 GList *tmp_geocode_list = (GList *)geocode_list;
952                 const DecartaGeocode *geocode = NULL;
953                 tmp_geocode_list = decarta_geocode_list_next(tmp_geocode_list, &geocode);
954
955                 while (geocode) {
956                         pos = get_location_pos_from_decarta_pos (geocode->pos);
957                         if (geocode->addr) acc = get_location_acc_from_decarta_addr (geocode->addr);
958                         else               acc = get_location_acc_from_free_addr (addr);
959
960                         DECARTA_LOGD("location decarta plugin: get_geocode_freetext %d, lat %f, lon %f ", i++, pos->latitude, pos->longitude);
961
962                         *position_list = g_list_append (*position_list, (gpointer)pos);
963                         *accuracy_list = g_list_append (*accuracy_list, (gpointer)acc);
964
965                         if (!tmp_geocode_list) break;
966                         tmp_geocode_list = decarta_geocode_list_next(tmp_geocode_list, &geocode);
967                 }
968                 decarta_geocode_list_free (geocode_list);
969         }
970         return convert_decarta_error_to_location_error (ret);
971 }
972
973
974 static int
975 get_geocode_freetext_async (gpointer handle,
976         const gchar* addr,
977         const LocationMapPref *svc_pref,
978         LocationPositionCB callback,
979         gpointer userdata)
980 {
981         DECARTA_LOGD("get_geocode_freetext_async");
982         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
983         g_return_val_if_fail (addr, LOCATION_ERROR_PARAMETER);
984         g_return_val_if_fail (callback, LOCATION_ERROR_PARAMETER);
985
986         char *ID = NULL;
987         char *password = NULL;
988         ID = location_map_pref_get_property(svc_pref, "ID");
989         password = location_map_pref_get_property(svc_pref, "PASSWORD");
990         set_config(ID, password, NULL, NULL);
991
992         char *language_code = NULL;
993         char *country_code = NULL;
994         language_code = location_map_pref_get_language(svc_pref);
995         country_code = location_map_pref_get_country(svc_pref);
996         if (language_code == NULL || country_code == NULL) {
997                 gchar tmp_country[3] = "";
998                 gchar tmp_language[3] = "";
999                 get_lang(tmp_country, tmp_language);
1000                 if (country_code == NULL) {
1001                         country_code = g_strdup(tmp_country);
1002                 }
1003                 if (language_code == NULL) {
1004                         language_code = g_strdup(tmp_language);
1005                 }
1006         }
1007
1008         DecartaData* data = g_new0(DecartaData, 1);
1009         DecartaAddress *deca_addr = decarta_address_new (country_code, language_code, TRUE, addr, NULL);
1010         data->pos_cb = callback;
1011         data->userdata = (gpointer)userdata;
1012         data->userdata2 = (gpointer)get_location_acc_from_decarta_addr (deca_addr);
1013
1014         // should call decarta_search_geocode_async in idle, OR request may be missed
1015         decarta_IdleData* idle_data= g_new0 (decarta_IdleData, 1);
1016         idle_data->addr = deca_addr;
1017         idle_data->geocode_cb = position_cb;
1018         idle_data->decarta_data = data;
1019         g_idle_add((GSourceFunc)decarta_idle_geocode_cb, (gpointer)idle_data);
1020
1021         return LOCATION_ERROR_NONE;
1022 }
1023
1024 static int
1025 get_reverse_geocode(gpointer handle,
1026         const LocationPosition *pos,
1027         const LocationMapPref *svc_pref,
1028         LocationAddress **addr,
1029         LocationAccuracy **accuracy)
1030 {
1031         DECARTA_LOGD("get_reverse_geocode");
1032         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
1033         g_return_val_if_fail(pos, LOCATION_ERROR_PARAMETER);
1034         g_return_val_if_fail(addr, LOCATION_ERROR_PARAMETER);
1035         g_return_val_if_fail(accuracy, LOCATION_ERROR_PARAMETER);
1036
1037         char *ID = NULL;
1038         char *password = NULL;
1039         ID = location_map_pref_get_property(svc_pref, "ID");
1040         password = location_map_pref_get_property(svc_pref, "PASSWORD");
1041         set_config(ID, password, NULL, NULL);
1042
1043         DecartaGeocode *geocode = NULL;
1044         DecartaPosition *deca_pos = decarta_position_new (pos->latitude, pos->longitude);
1045         int ret = decarta_search_reverse_geocode(deca_pos, &geocode);
1046         decarta_position_free (deca_pos);
1047
1048         if (ret == DECARTA_ERROR_NONE) {
1049                 if (geocode) {
1050                         *addr = get_location_addr_from_decarta_addr (geocode->addr);
1051                         *accuracy = get_location_acc_from_decarta_addr (geocode->addr);
1052                         decarta_geocode_free (geocode);
1053                 }
1054         }
1055
1056         return convert_decarta_error_to_location_error (ret);
1057 }
1058
1059 static gboolean
1060 decarta_idle_reverse_geocode_cb (gpointer data)
1061 {
1062         DECARTA_LOGD("decarta_idle_reverse_geocode_cb");
1063         decarta_IdleData* idle_data = (decarta_IdleData*)data;
1064         if (idle_data == NULL || idle_data->decarta_data == NULL) {
1065                 DECARTA_LOGD("idle_data or decarta_data is NULL");
1066                 return FALSE;
1067         }
1068
1069         DecartaData *deca_data = (DecartaData *)idle_data->decarta_data;
1070         int err = decarta_search_reverse_geocode_async (idle_data->pos, idle_data->reverse_geocode_cb, deca_data, &deca_data->handle);
1071         async_request_queue  = g_slist_prepend(async_request_queue , deca_data->handle);
1072         if (DECARTA_ERROR_NONE != err) {
1073                 DECARTA_LOGD("Decarta Reverse Geocode Failed: %d", err);
1074
1075                 // call address_cb() to return the error code, and free DecartaData
1076                 if (idle_data->reverse_geocode_cb) {
1077                         idle_data->reverse_geocode_cb (err, NULL, idle_data->decarta_data);
1078                 }
1079         }
1080         decarta_position_free (idle_data->pos);
1081         g_free (idle_data);
1082         return FALSE;
1083 }
1084
1085 static int
1086 get_reverse_geocode_async (gpointer handle,
1087         const LocationPosition *pos,
1088         const LocationMapPref *svc_pref,
1089         LocationAddressCB callback,
1090         gpointer userdata)
1091 {
1092         DECARTA_LOGD("get_reverse_geocode_async");
1093         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
1094         g_return_val_if_fail(pos, LOCATION_ERROR_PARAMETER);
1095         g_return_val_if_fail(callback, LOCATION_ERROR_PARAMETER);
1096
1097         char *ID = NULL;
1098         char *password = NULL;
1099         ID = location_map_pref_get_property(svc_pref, "ID");
1100         password = location_map_pref_get_property(svc_pref, "PASSWORD");
1101         set_config(ID, password, NULL, NULL);
1102
1103         DecartaData* data = g_new0(DecartaData, 1);
1104         data->addr_cb = callback;
1105         data->userdata = (gpointer)userdata;
1106         DecartaPosition *deca_pos = decarta_position_new (pos->latitude, pos->longitude);
1107
1108         // should call decarta_search_reverse_geocode_async in idle, OR request may be missed
1109         decarta_IdleData* idle_data= g_new0 (decarta_IdleData, 1);
1110         idle_data->pos= deca_pos;
1111         idle_data->reverse_geocode_cb= address_cb;
1112         idle_data->decarta_data = data;
1113         g_idle_add((GSourceFunc)decarta_idle_reverse_geocode_cb, (gpointer)idle_data);
1114
1115         return LOCATION_ERROR_NONE;
1116 }
1117
1118
1119 static DecartaPOIPrefSortOrder
1120 decarta_get_sort_order(LocationPOIPrefSortOrder order)
1121 {
1122         if (order == LOCATION_POI_PREF_SO_ASC) {
1123                 return DECARTA_POI_PREF_SO_ASC;
1124         } else if (order == LOCATION_POI_PREF_SO_DESC) {
1125                 return DECARTA_POI_PREF_SO_DESC;
1126         } else {
1127                 return DECARTA_POI_PREF_SO_NONE;
1128         }
1129 }
1130
1131 //to make the request_id unique int, not start with 0
1132 static guint request_id = 1;
1133
1134 static gboolean
1135 decarta_idle_directory_cb (gpointer data)
1136 {
1137         decarta_IdleData* idle_data = (decarta_IdleData*)data;
1138         if (idle_data == NULL) {
1139                 g_printf( "decarta_IdleData is NULL\n");
1140                 return FALSE;
1141         }
1142
1143         int err = decarta_search_directory_async (idle_data->dir_request, idle_data->dir_cb, idle_data->decarta_data);
1144         if (DECARTA_ERROR_NONE != err) {
1145                 g_printf( "Decarta Directory Failed: %d\n", err);
1146
1147                 // call landmark_cb() to return the error code, and free DecartaData
1148                 if (idle_data->dir_cb) {
1149                         char req_id_str[256];
1150                         g_snprintf(req_id_str, 256, "%d", idle_data->request_id);
1151                         idle_data->dir_cb (err, req_id_str, NULL, NULL, NULL, idle_data->decarta_data);
1152                 }
1153         }
1154         decarta_directory_request_free (idle_data->dir_request);
1155         g_free (idle_data);
1156         return FALSE;
1157 }
1158
1159 int search_poi(gpointer handle,
1160         const LocationPOIFilter *filter,
1161         const LocationPosition *position,
1162         const LocationMapPref *svc_pref,
1163         const LocationPOIPreference *pref,
1164         LocationPOICB cb,
1165         gpointer user_data,
1166         guint *req_id)
1167 {
1168         DECARTA_LOGD("location decarta plugin: search_poi");
1169         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
1170         g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER);
1171         g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER);
1172         g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER);
1173         g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER);
1174         g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER);
1175
1176         char *ID = NULL;
1177         char *password = NULL;
1178         ID = location_map_pref_get_property(svc_pref, "ID");
1179         password = location_map_pref_get_property(svc_pref, "PASSWORD");
1180         set_config(ID, password, NULL, NULL);
1181
1182         DecartaData* data = g_new0(DecartaData, 1);
1183         DecartaPosition *pos = decarta_position_new (position->latitude, position->longitude);
1184         *req_id = request_id++;
1185         // POI property: keyword, brand, type, description, URL =>  CATEGORY, KEYWORD, POIName
1186         const char *type = location_poi_filter_get(filter, "CATEGORY");
1187         const char *keyword = location_poi_filter_get(filter, "KEYWORD");
1188         const char *poi_name = location_poi_filter_get(filter, "POIName");
1189         DecartaPOIProperty *property = decarta_poi_property_new (poi_name, keyword, NULL, type, NULL, NULL);
1190         DecartaPOIPreference *poi_pref = decarta_poi_preference_new(location_poi_pref_get_max_result(pref),
1191                                 decarta_get_sort_order(location_poi_pref_get_sort_order(pref)), location_poi_pref_get_sort_by(pref));
1192         DecartaDirectoryRequest *dir_request = decarta_directory_request_new (poi_pref, DECARTA_DIRECTORY_SEARCH_TYPE_NEAREST,
1193                                                                                 DECARTA_DIRECTORY_TYPE_POS, pos, NULL, NULL, property, 0, *req_id);
1194         decarta_position_free (pos);
1195         decarta_poi_property_free (property);
1196         decarta_poi_preference_free(poi_pref);
1197
1198
1199         data->poi_cb = cb;
1200         data->userdata = (gpointer)user_data;
1201
1202         // should call decarta_search_directory_async in idle, OR request may be missed
1203         decarta_IdleData* idle_data= g_new0 (decarta_IdleData, 1);
1204         idle_data->dir_request = dir_request;
1205         idle_data->dir_cb = landmark_cb;
1206         idle_data->decarta_data = data;
1207         idle_data->request_id = request_id;
1208         g_idle_add((GSourceFunc)decarta_idle_directory_cb, (gpointer)idle_data);
1209
1210         return LOCATION_ERROR_NONE;
1211 }
1212
1213 int search_poi_by_area(gpointer handle,
1214         const LocationPOIFilter *filter,
1215         const LocationBoundary *boundary,
1216         const LocationMapPref *svc_pref,
1217         const LocationPOIPreference *pref,
1218         LocationPOICB cb,
1219         gpointer user_data,
1220         guint *req_id)
1221 {
1222         DECARTA_LOGD("location decarta plugin: search_poi_by_area");
1223         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
1224         g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER);
1225         g_return_val_if_fail (boundary, LOCATION_ERROR_PARAMETER);
1226         g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER);
1227         g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER);
1228         g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER);
1229
1230         char *ID = NULL;
1231         char *password = NULL;
1232         ID = location_map_pref_get_property(svc_pref, "ID");
1233         password = location_map_pref_get_property(svc_pref, "PASSWORD");
1234         set_config(ID, password, NULL, NULL);
1235
1236         if (boundary->type == LOCATION_BOUNDARY_CIRCLE) {
1237                 DecartaData* data = g_new0(DecartaData, 1);
1238                 DecartaPosition *pos = decarta_position_new (boundary->circle.center->latitude, boundary->circle.center->longitude);
1239                 double distance = boundary->circle.radius;
1240                 DECARTA_LOGD("search_poi_by_area: Circle lat [%lf], lon [%lf], radius [%f]",
1241                                 boundary->circle.center->latitude,
1242                                 boundary->circle.center->longitude,
1243                                 distance);
1244                 *req_id = request_id++;
1245                 const char *type = location_poi_filter_get(filter, "CATEGORY");
1246                 const char *keyword = location_poi_filter_get(filter, "KEYWORD");
1247                 const char *poi_name = location_poi_filter_get(filter, "POIName");
1248                 DecartaPOIProperty *property = decarta_poi_property_new (poi_name, keyword, NULL, type, NULL, NULL);
1249                 DecartaPOIPreference *poi_pref = decarta_poi_preference_new(location_poi_pref_get_max_result(pref),
1250                                 decarta_get_sort_order(location_poi_pref_get_sort_order(pref)), location_poi_pref_get_sort_by(pref));
1251                 DecartaDirectoryRequest *dir_request = decarta_directory_request_new (poi_pref, DECARTA_DIRECTORY_SEARCH_TYPE_WITHIN_DISTANCE,
1252                                                                                         DECARTA_DIRECTORY_TYPE_POS, pos, NULL, NULL, property, distance, *req_id);
1253                 decarta_position_free (pos);
1254                 decarta_poi_property_free (property);
1255                 decarta_poi_preference_free(poi_pref);
1256
1257                 data->poi_cb = cb;
1258                 data->userdata = (gpointer)user_data;
1259
1260                 // should call decarta_search_directory_async in idle, OR request may be missed
1261                 decarta_IdleData* idle_data= g_new0 (decarta_IdleData, 1);
1262                 idle_data->dir_request = dir_request;
1263                 idle_data->dir_cb = landmark_cb;
1264                 idle_data->decarta_data = data;
1265                 idle_data->request_id = request_id;
1266                 g_idle_add((GSourceFunc)decarta_idle_directory_cb, (gpointer)idle_data);
1267
1268                 return LOCATION_ERROR_NONE;
1269         } else if (boundary->type == LOCATION_BOUNDARY_RECT) {
1270                 return LOCATION_ERROR_NOT_AVAILABLE;
1271         } else if (boundary->type == LOCATION_BOUNDARY_POLYGON) {
1272                 return LOCATION_ERROR_NOT_AVAILABLE;
1273         } else {
1274                 return LOCATION_ERROR_NOT_AVAILABLE;
1275         }
1276 }
1277
1278 int search_poi_by_address(gpointer handle,
1279         const LocationPOIFilter *filter,
1280         const LocationAddress *addr,
1281         const LocationMapPref *svc_pref,
1282         const LocationPOIPreference *pref,
1283         LocationPOICB cb,
1284         gpointer user_data,
1285         guint *req_id)
1286 {
1287         DECARTA_LOGD("location decarta plugin: search_poi_by_addr");
1288         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
1289         g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER);
1290         g_return_val_if_fail (addr, LOCATION_ERROR_PARAMETER);
1291         g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER);
1292         g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER);
1293         g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER);
1294
1295         char *ID = NULL;
1296         char *password = NULL;
1297         ID = location_map_pref_get_property(svc_pref, "ID");
1298         password = location_map_pref_get_property(svc_pref, "PASSWORD");
1299         set_config(ID, password, NULL, NULL);
1300
1301         char *language_code = NULL;
1302         char *country_code = NULL;
1303         language_code = location_map_pref_get_language(svc_pref);
1304         country_code = location_map_pref_get_country(svc_pref);
1305         if (language_code == NULL || country_code == NULL) {
1306                 gchar tmp_country[3] = "";
1307                 gchar tmp_language[3] = "";
1308                 get_lang(tmp_country, tmp_language);
1309                 if (country_code == NULL) {
1310                         country_code = g_strdup(tmp_country);
1311                 }
1312                 if (language_code == NULL) {
1313                         language_code = g_strdup(tmp_language);
1314                 }
1315         }
1316
1317         DecartaData* data = g_new0(DecartaData, 1);
1318
1319         // Fixme: landmark_type, landmark_name for decarta_formed_address_new ??
1320         DecartaFormedAddress *formed_addr = decarta_formed_address_new (addr->building_number, addr->street, addr->country_code,
1321                         addr->state, addr->city, addr->district, addr->postal_code, NULL, NULL);
1322
1323         *req_id = request_id++;
1324
1325         DecartaAddress *decarta_addr = decarta_address_new (country_code, language_code, FALSE, NULL, formed_addr);
1326         decarta_formed_address_free (formed_addr);
1327
1328         const char *type = location_poi_filter_get(filter, "CATEGORY");
1329         const char *keyword = location_poi_filter_get(filter, "KEYWORD");
1330         const char *poi_name = location_poi_filter_get(filter, "POIName");
1331         DecartaPOIProperty *property = decarta_poi_property_new (poi_name, keyword, NULL, type, NULL, NULL);
1332         DecartaPOIPreference *poi_pref = decarta_poi_preference_new(location_poi_pref_get_max_result(pref),
1333                                 decarta_get_sort_order(location_poi_pref_get_sort_order(pref)), location_poi_pref_get_sort_by(pref));
1334
1335         DecartaDirectoryRequest *dir_request = decarta_directory_request_new (poi_pref, DECARTA_DIRECTORY_SEARCH_TYPE_ADDRESS,
1336                                                                                 DECARTA_DIRECTORY_TYPE_ADDRESS, NULL, decarta_addr, NULL, property, 0, *req_id);
1337         decarta_address_free (decarta_addr);
1338         decarta_poi_property_free (property);
1339         decarta_poi_preference_free(poi_pref);
1340
1341         data->poi_cb = cb;
1342         data->userdata = (gpointer)user_data;
1343
1344         // should call decarta_search_directory_async in idle, OR request may be missed
1345         decarta_IdleData* idle_data= g_new0 (decarta_IdleData, 1);
1346         idle_data->dir_request = dir_request;
1347         idle_data->dir_cb = landmark_cb;
1348         idle_data->decarta_data = data;
1349         idle_data->request_id = request_id;
1350         g_idle_add((GSourceFunc)decarta_idle_directory_cb, (gpointer)idle_data);
1351
1352         return LOCATION_ERROR_NONE;
1353 }
1354
1355 int search_poi_by_freeform(gpointer handle,
1356         const LocationPOIFilter *filter,
1357         const gchar *address,
1358         const LocationMapPref *svc_pref,
1359         const LocationPOIPreference *pref,
1360         LocationPOICB cb,
1361         gpointer user_data,
1362         guint *req_id)
1363 {
1364         DECARTA_LOGD("location decarta plugin: search_poi_by_freeformed_address");
1365         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
1366         g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER);
1367         g_return_val_if_fail (address, LOCATION_ERROR_PARAMETER);
1368         g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER);
1369         g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER);
1370         g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER);
1371
1372         char *ID = NULL;
1373         char *password = NULL;
1374         ID = location_map_pref_get_property(svc_pref, "ID");
1375         password = location_map_pref_get_property(svc_pref, "PASSWORD");
1376         set_config(ID, password, NULL, NULL);
1377
1378         char *language_code = NULL;
1379         char *country_code = NULL;
1380         language_code = location_map_pref_get_language(svc_pref);
1381         country_code = location_map_pref_get_country(svc_pref);
1382         if (language_code == NULL || country_code == NULL) {
1383                 gchar tmp_country[3] = "";
1384                 gchar tmp_language[3] = "";
1385                 get_lang(tmp_country, tmp_language);
1386                 if (country_code == NULL) {
1387                         country_code = g_strdup(tmp_country);
1388                 }
1389                 if (language_code == NULL) {
1390                         language_code = g_strdup(tmp_language);
1391                 }
1392         }
1393
1394         DecartaData* data = g_new0(DecartaData, 1);
1395
1396         *req_id = request_id++;
1397
1398         DecartaAddress *free_addr = decarta_address_new (country_code, language_code, TRUE, address, NULL);
1399
1400         const char *type = location_poi_filter_get(filter, "CATEGORY");
1401         const char *keyword = location_poi_filter_get(filter, "KEYWORD");
1402         const char *poi_name = location_poi_filter_get(filter, "POIName");
1403         DecartaPOIProperty *property = decarta_poi_property_new (poi_name, keyword, NULL, type, NULL, NULL);
1404
1405         DecartaPOIPreference *poi_pref = decarta_poi_preference_new(location_poi_pref_get_max_result(pref),
1406                                 decarta_get_sort_order(location_poi_pref_get_sort_order(pref)), location_poi_pref_get_sort_by(pref));
1407         DecartaDirectoryRequest *dir_request = decarta_directory_request_new (poi_pref, DECARTA_DIRECTORY_SEARCH_TYPE_ADDRESS,
1408                                                                                 DECARTA_DIRECTORY_TYPE_ADDRESS, NULL, free_addr, NULL, property, 0, *req_id);
1409
1410         decarta_address_free (free_addr);
1411         decarta_poi_property_free (property);
1412         decarta_poi_preference_free(poi_pref);
1413
1414         data->poi_cb = cb;
1415         data->userdata = (gpointer)user_data;
1416
1417         // should call decarta_search_directory_async in idle, OR request may be missed
1418         decarta_IdleData* idle_data= g_new0 (decarta_IdleData, 1);
1419         idle_data->dir_request = dir_request;
1420         idle_data->dir_cb = landmark_cb;
1421         idle_data->decarta_data = data;
1422         idle_data->request_id = request_id;
1423         g_idle_add((GSourceFunc)decarta_idle_directory_cb, (gpointer)idle_data);
1424
1425         return LOCATION_ERROR_NONE;
1426 }
1427
1428 int cancel_poi_request(gpointer handle,
1429         guint req_id)
1430 {
1431         DECARTA_LOGD("location decarta plugin: cancel_poi_request");
1432         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
1433
1434         decarta_search_directory_async_cancel (req_id);
1435         return LOCATION_ERROR_NONE;
1436 }
1437
1438 static void
1439 __route_create_via_list (gpointer data,
1440         gpointer user_data)
1441 {
1442         LocationPosition *via_loc_pos = (LocationPosition *)data;
1443         GList **via_geocode_list = (GList **)user_data;
1444
1445         DecartaPosition *via_pos = decarta_position_new (via_loc_pos->latitude, via_loc_pos->longitude);
1446         *via_geocode_list = decarta_geocode_list_append (*via_geocode_list, decarta_geocode_new (via_pos, NULL));
1447         decarta_position_free (via_pos);
1448 }
1449
1450 static DecartaRoutePreference
1451 __get_route_type(const gchar *type)
1452 {
1453         if (0 == g_strcmp0("FASTEST", type)) {
1454                 return DECARTA_ROUTE_PREF_FASTEST;
1455         } else if (0 == g_strcmp0("SHORTEST", type)) {
1456                 return DECARTA_ROUTE_PREF_SHORTEST;
1457         } else if (0 == g_strcmp0("PEDESTRIAN", type)) {
1458                 return DECARTA_ROUTE_PREF_PEDESTRIAN;
1459         } else if (0 == g_strcmp0("AVOID_FREEWAYS", type)) {
1460                 return DECARTA_ROUTE_PREF_AVOID_FREEWAYS;
1461         } else if (0 == g_strcmp0("NO_FREEWAYS", type)) {
1462                 return DECARTA_ROUTE_PREF_NO_FREEWAYS;
1463         } else if (0 == g_strcmp0("MORE_FREEWAYS", type)) {
1464                 return DECARTA_ROUTE_PREF_MORE_FREEWAYS;
1465         } else if (0 == g_strcmp0("IGNORE_PIPES", type)) {
1466                 return DECARTA_ROUTE_PREF_IGNORE_PIPES;
1467         } else if (0 == g_strcmp0("EASY", type)) {
1468                 return DECARTA_ROUTE_PREF_EASY;
1469         } else {
1470                 return DECARTA_ROUTE_PREF_NONE;
1471         }
1472 }
1473
1474 static gboolean
1475 decarta_idle_route_cb (gpointer data)
1476 {
1477         decarta_IdleData* idle_data = (decarta_IdleData*)data;
1478         if (idle_data == NULL) {
1479                 g_printf( "idle_data is NULL\n");
1480                 return FALSE;
1481         }
1482
1483         int err = decarta_search_route_async (idle_data->route_request, idle_data->route_cb, idle_data->decarta_data);
1484         if (DECARTA_ERROR_NONE != err) {
1485                 g_printf("Decarta Route Failed: %d\n", err);
1486
1487                 // call route_callback() to return the error code, and free DecartaData
1488                 if (idle_data->route_cb) {
1489                         char req_id_str[256];
1490                         g_snprintf(req_id_str, 256, "%d", idle_data->request_id);
1491                         idle_data->route_cb (err, req_id_str, NULL, NULL, NULL, idle_data->decarta_data);
1492                 }
1493         }
1494         decarta_route_request_free (idle_data->route_request);
1495         g_free(idle_data);
1496         return FALSE;
1497 }
1498
1499 int request_route (gpointer handle,
1500         const LocationPosition *origin,
1501         const LocationPosition *destination,
1502         GList *waypoint,
1503         const LocationMapPref *svc_pref,
1504         const LocationRoutePreference *pref,
1505         LocationRouteCB cb,
1506         const gpointer user_data,
1507         guint *req_id)
1508 {
1509         DECARTA_LOGD("location decarta plugin: request_route");
1510         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
1511         g_return_val_if_fail (origin, LOCATION_ERROR_PARAMETER);
1512         g_return_val_if_fail (destination, LOCATION_ERROR_PARAMETER);
1513         g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER);
1514         g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER);
1515         g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER);
1516
1517         char *ID = NULL;
1518         char *password = NULL;
1519         ID = location_map_pref_get_property(svc_pref, "ID");
1520         password = location_map_pref_get_property(svc_pref, "PASSWORD");
1521         set_config(ID, password, NULL, NULL);
1522
1523         char *language_code = NULL;
1524         char *maneuver_rules = NULL;
1525         language_code = location_map_pref_get_language(svc_pref);
1526         if (language_code == NULL) {
1527                 gchar tmp_country[3] = "";
1528                 gchar tmp_language[3] = "";
1529                 get_lang(tmp_country, tmp_language);
1530                 language_code = g_strdup(tmp_language);
1531         }
1532         if (!g_strcmp0(language_code, "FR")) {
1533                 maneuver_rules = g_strdup_printf("maneuver-rules-%s", language_code);
1534         } else {
1535                 maneuver_rules = g_strdup("maneuver-rules");
1536         }
1537
1538         char *dist_uit = NULL;
1539         dist_uit = location_map_pref_get_distance_unit(svc_pref);
1540         if (g_strcmp0(dist_uit, "KM") != 0 && g_strcmp0(dist_uit, "M") != 0 && g_strcmp0(dist_uit, "DM") != 0 &&
1541                 g_strcmp0(dist_uit, "MI") != 0 && g_strcmp0(dist_uit, "YD") != 0 && g_strcmp0(dist_uit, "FT") != 0) {
1542                 dist_uit = g_strdup("M");
1543         }
1544
1545         DecartaData* data = g_new0(DecartaData, 1);
1546         DecartaPosition *start_pos = decarta_position_new (origin->latitude, origin->longitude);
1547         DecartaPosition *end_pos = decarta_position_new (destination->latitude, destination->longitude);
1548
1549         DecartaGeocode *start = decarta_geocode_new (start_pos, NULL);
1550         DecartaGeocode *end = decarta_geocode_new (end_pos, NULL);
1551         GList *via_geocode_list = NULL;
1552         GList *tmp_waypoint = (GList *)waypoint;
1553         if (tmp_waypoint) {
1554                 g_list_foreach(tmp_waypoint, (GFunc)__route_create_via_list, &via_geocode_list);
1555         }
1556         decarta_position_free (start_pos);
1557         decarta_position_free (end_pos);
1558
1559         gboolean bbox_needed = FALSE;
1560         DecartaPosition *bbox_pos1 = NULL;
1561         DecartaPosition *bbox_pos2 = NULL;
1562         LocationBoundary *bbox = location_route_pref_get_bounding_box(pref);
1563         if (bbox && bbox->type == LOCATION_BOUNDARY_RECT) {
1564                 bbox_pos1 = decarta_position_new(bbox->rect.left_top->latitude, bbox->rect.left_top->longitude);
1565                 bbox_pos2 = decarta_position_new(bbox->rect.right_bottom->latitude, bbox->rect.right_bottom->longitude);
1566                 bbox_needed = TRUE;
1567         }
1568
1569         float resolution = DEFAULT_ROUTE_RESOLUTION;
1570         char *reslolution_str = (char *)location_route_pref_get_property(pref, (gconstpointer)"resolution");
1571         if (reslolution_str) {
1572                 resolution = (float)g_ascii_strtod(reslolution_str, NULL);
1573         }
1574
1575         *req_id = request_id++;
1576         DecartaRouteRequest *route_request = decarta_route_request_new (__get_route_type(location_route_pref_get_route_type(pref)),
1577                                 start, end, via_geocode_list, TRUE, TRUE,
1578                                 bbox_needed, bbox_pos1, bbox_pos2, TRUE, resolution, TRUE, *req_id, dist_uit, maneuver_rules);
1579         g_free (maneuver_rules);
1580         decarta_geocode_free (start);
1581         decarta_geocode_free (end);
1582         if (via_geocode_list) {
1583                 decarta_geocode_list_free (via_geocode_list);
1584                 via_geocode_list = NULL;
1585         }
1586         if (bbox_pos1) {
1587                 decarta_position_free(bbox_pos1);
1588         }
1589         if (bbox_pos2) {
1590                 decarta_position_free(bbox_pos2);
1591         }
1592
1593         data->route_cb = cb;
1594         data->userdata = (gpointer)user_data;
1595         data->userdata2 = (gpointer)location_position_copy(origin);
1596         data->userdata3 = (gpointer)location_position_copy(destination);
1597
1598         // should call decarta_search_route_async in idle callback, OR request may be missed
1599         decarta_IdleData* idle_data= g_new0 (decarta_IdleData, 1);
1600         idle_data->route_request = route_request;
1601         idle_data->route_cb= route_callback;
1602         idle_data->decarta_data = data;
1603         idle_data->request_id = request_id;
1604         g_idle_add((GSourceFunc)decarta_idle_route_cb, (gpointer)idle_data);
1605
1606         return LOCATION_ERROR_NONE;
1607 }
1608 int cancel_route_request (gpointer handle,
1609         guint req_id)
1610 {
1611         int ret = DECARTA_ERROR_NONE;
1612
1613         DECARTA_LOGD("location decarta plugin: request_route");
1614         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
1615
1616         ret = decarta_search_route_async_cancel (req_id);
1617         if (ret != DECARTA_ERROR_NONE) {
1618                 return convert_decarta_error_to_location_error(ret);
1619         }
1620         
1621         return LOCATION_ERROR_NONE;
1622 }
1623
1624 static gboolean
1625 is_supported_provider_capability (gpointer handle, LocationMapServiceType type)
1626 {
1627         DECARTA_LOGD("location decarta plugin: is_supported_provider_capability");
1628         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
1629
1630         return g_capa_list[type];
1631 }
1632
1633 static int
1634 get_provider_capability_key (gpointer handle, LocationMapServiceType type, GList **key)
1635 {
1636         DECARTA_LOGD("location decarta plugin: get_provider_capability_key");
1637         g_return_val_if_fail(handle == (gpointer)service_name, LOCATION_ERROR_NOT_AVAILABLE);
1638         g_return_val_if_fail (key, LOCATION_ERROR_PARAMETER);
1639
1640         gchar **str_key = NULL;
1641         int idx = 0, count = 0;
1642         gchar *available_key = NULL;
1643
1644         switch (type) {
1645                 case MAP_SERVICE_PREF_LANGUAGE:
1646                         str_key = key_lang;
1647                         count = sizeof(key_lang) / sizeof(char *);
1648                         g_printf("key_lang[%d], char *[%d]. Count [%d]", sizeof(key_lang), sizeof(char*), count);
1649
1650                         break;
1651                 case MAP_SERVICE_PREF_PROPERTY:
1652                         str_key = key_property;
1653                         count = sizeof(key_property) / sizeof(char *);
1654                         g_printf("key_property[%d], char *[%d]. Count [%d]", sizeof(key_property), sizeof(char*), count);
1655                         break;
1656                 case MAP_SERVICE_PREF_DISTANCE_UNIT:
1657                 case MAP_SERVICE_ROUTE_DISTANCE_UNIT:
1658                         str_key = key_dist;
1659                         count = sizeof(key_dist) / sizeof(char*);
1660                         break;
1661                 case MAP_SERVICE_POI_PREF_SORT_BY:
1662                         str_key = key_poi_sort;
1663                         count = sizeof(key_poi_sort) / sizeof (char*);
1664                         break;
1665                 case MAP_SERVICE_POI_PREF_PROPERTY:
1666                         str_key = key_poi_prop;
1667                         count = sizeof(key_poi_prop) / sizeof (char*);
1668                         break;
1669                 case MAP_SERVICE_POI_FILTER:
1670                         str_key = key_poi_filter;
1671                         count = sizeof(key_poi_filter) / sizeof (char*);
1672                         break;
1673                 case MAP_SERVICE_POI_FILTER_CATEGORY:
1674                         str_key = key_poi_filter_category;
1675                         count = sizeof(key_poi_filter_category) / sizeof (char*);
1676                         break;
1677                 case MAP_SERVICE_ROUTE_REQUEST_FEATURE_TO_AVOID:
1678                         str_key = key_route_feature_to_avoid;
1679                         count = sizeof(key_route_feature_to_avoid) / sizeof (char*);
1680                         break;
1681                 case MAP_SERVICE_ROUTE_PREF_TYPE:
1682                         str_key = key_route_type;
1683                         count = sizeof(key_route_type) / sizeof (char*);
1684                         break;
1685                 case MAP_SERVICE_ROUTE_PREF_TRANSPORT_MODE:
1686                         str_key = key_route_trans_mode;
1687                         count = sizeof(key_route_trans_mode) / sizeof (char*);
1688                         break;
1689                 default:
1690                         str_key = NULL;
1691                         break;
1692         }
1693
1694         if (!str_key) {
1695                 *key = NULL;
1696                 return LOCATION_ERROR_NOT_FOUND;
1697         }
1698
1699         for (idx = 0; idx < count; idx++) {
1700                 available_key = g_strdup (str_key[idx]);
1701                 *key = g_list_append(*key, available_key);
1702         }
1703
1704         return LOCATION_ERROR_NONE;
1705 }
1706
1707 LOCATION_MODULE_API gpointer
1708 init (LocModServiceOps* ops)
1709 {
1710         DECARTA_LOGD("init");
1711         g_return_val_if_fail(ops, NULL);
1712         gpointer handle = (gpointer)service_name;
1713
1714         ops->get_service_name = get_service_name;
1715         ops->get_geocode = get_geocode;
1716         ops->get_geocode_freetext = get_geocode_freetext;
1717         ops->get_reverse_geocode = get_reverse_geocode;
1718         ops->get_geocode_async = get_geocode_async;
1719         ops->get_geocode_freetext_async = get_geocode_freetext_async;
1720         ops->get_reverse_geocode_async = get_reverse_geocode_async;
1721
1722         ops->search_poi = search_poi;
1723         ops->search_poi_by_area = search_poi_by_area;
1724         ops->search_poi_by_address = search_poi_by_address;
1725         ops->search_poi_by_freeform = search_poi_by_freeform;
1726         ops->cancel_poi_request = cancel_poi_request;
1727
1728         ops->request_route = request_route;
1729         ops->cancel_route_request = cancel_route_request;
1730
1731         ops->is_supported_provider_capability = is_supported_provider_capability;
1732         ops->get_provider_capability_key = get_provider_capability_key;
1733
1734         async_request_queue = g_slist_alloc();
1735         return handle;
1736 }
1737
1738 static void
1739 cancel_request (gpointer data, gpointer user_data)
1740 {
1741         decarta_search_geocode_async_cancel(data);
1742         decarta_search_reverse_geocode_async_cancel(data);
1743 }
1744
1745 LOCATION_MODULE_API void
1746 shutdown (gpointer handle)
1747 {
1748         DECARTA_LOGD("shutdown");
1749         g_return_if_fail(handle == (gpointer)service_name);
1750
1751         g_slist_foreach (async_request_queue, cancel_request, NULL);
1752
1753         g_slist_free(async_request_queue);
1754 }