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