+/*
+ * Copyright (c) 2019 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hs-vuiadapter.h"
+#include "hs-clientmanager.h"
+#include "hs-proxy.h"
+#include "hs-appinfo.h"
+
+/**
+ * event handler
+ *
+ * #### Parameters
+ * - api : the api
+ * - event : received event name
+ * - object : received json object
+ *
+ * #### Return
+ * 0 : event can transfer to others
+ * 1 : event not transfer to others
+ */
+int event_handler(afb_api_t api, const char *event, struct json_object *object)
+{
+ return HS_VuiAdapter::instance()->onEvent(api, event, object);
+}
+
+/* -------------------------------------Vui_Navigation------------------------------------------ */
+
+const std::map<std::string, Vui_Navigation::func_handler> Vui_Navigation::func_list = {
+ {"set_destination", &Vui_Navigation::set_destination},
+ {"cancel_navigation", &Vui_Navigation::cancel_navigation}
+};
+const char _vui_prefixe[] = "vui";
+const char _poi[] = "poi";
+const char _navigation[] = "navigation";
+const char _destination[] = "destination";
+const char _coordinate[] = "coordinate";
+const char _latitudeInDegrees[] = "latitudeInDegrees";
+const char _longitudeInDegrees[] = "longitudeInDegrees";
+const char _setDestination[] = "setDestination";
+const char _cancelDestination[] = "cancelDestination";
+const char _startNavigation[] = "startNavigation";
+const char _stopNavigation[] = "stopNavigation";
+
+/**
+ * init
+ *
+ * #### Parameters
+ * - api : the api
+ *
+ * #### Return
+ * None
+ *
+ */
+void Vui_Navigation::init(afb_api_t api)
+{
+ std::list<std::string> ev_list;
+ for(auto &it : func_list) {
+ ev_list.push_back(it.first);
+ std::string ev_name = std::string(_vshl_capabilities) + '/' + it.first;
+ AFB_INFO("setEventHook event %s", ev_name.c_str());
+ setEventHook(ev_name.c_str(), event_handler);
+ }
+ HS_VshlCapabilitiesProxy proxy;
+ proxy.subscribe(api, _navigation, ev_list);
+}
+
+/**
+ * handle event
+ *
+ * #### Parameters
+ * - api : the api serving the request
+ * - event : event name
+ * - object : event json object
+ *
+ * #### Return
+ * 0 : continue transfer
+ * 1 : blocked
+ *
+ */
+int Vui_Navigation::onEvent(afb_api_t api, const char *event, struct json_object *object)
+{
+ std::string ev(event);
+ auto pos = ev.find('/');
+ auto ip = func_list.find(ev.substr(pos + 1));
+ int ret = 0;
+ if(ip != func_list.end()) {
+ (this->*(ip->second))(api, object);
+ ret = 1;
+ }
+ return ret;
+}
+
+/**
+ * set_destination event handler
+ *
+ * #### Parameters
+ * - api : the api serving the reques
+ * - object : event json object
+ *
+ * #### Return
+ * None
+ *
+ */
+void Vui_Navigation::set_destination(afb_api_t api, struct json_object *object)
+{
+ AFB_INFO("set dest: %s", json_object_to_json_string(object));
+ struct json_object *j_dest, *j_coord, *j_latitude, *j_longitude;
+ struct json_object *j_obj = json_tokener_parse(json_object_get_string(object));
+ if(json_object_object_get_ex(j_obj, _destination, &j_dest)
+ && json_object_object_get_ex(j_dest, _coordinate, &j_coord)
+ && json_object_object_get_ex(j_coord, _latitudeInDegrees, &j_latitude)
+ && json_object_object_get_ex(j_coord, _longitudeInDegrees, &j_longitude)) {
+ m_dest = std::make_pair(json_object_get_double(j_latitude), json_object_get_double(j_longitude));
+ }
+ else {
+ AFB_WARNING("input data error.");
+ return;
+ }
+
+ auto b_pair = std::make_pair<bool, bool>(false, false);
+ if(HS_ClientManager::instance()->isAppStarted(std::string(_poi))) {
+ b_pair.first = true;
+ set_destination2poi(api);
+ }
+ else {
+ this->addListenAppId(_poi);
+ std::string id = HS_AppInfo::instance()->getAppProperty(_poi, _keyId);
+ HS_AfmMainProxy afm_proxy;
+ afm_proxy.start(api, id);
+ }
+
+ if(HS_ClientManager::instance()->isAppStarted(std::string(_navigation))) {
+ b_pair.second = true;
+ start_navigation(api);
+ }
+ else {
+ this->addListenAppId(_navigation);
+ std::string id = HS_AppInfo::instance()->getAppProperty(_navigation, _keyId);
+ HS_AfmMainProxy afm_proxy;
+ afm_proxy.start(api, id);
+ }
+ m_start_flg.swap(b_pair);
+ if (!listenAppEmpty()) {
+ HS_ClientManager::instance()->addListener(this);
+ }
+}
+
+/**
+ * cancel_navigation event handler
+ *
+ * #### Parameters
+ * - api : the api serving the reques
+ * - object : event json object
+ *
+ * #### Return
+ * None
+ *
+ */
+void Vui_Navigation::cancel_navigation(afb_api_t api, struct json_object *object)
+{
+ HS_ClientManager::instance()->pushEvent(_stopNavigation, nullptr);
+}
+
+/**
+ * notify
+ *
+ * #### Parameters
+ * - api : the api
+ * - appid : application id
+ *
+ * #### Return
+ * None
+ *
+ */
+void Vui_Navigation::notify(afb_api_t api, std::string appid)
+{
+ if(isListenAppId(appid)) {
+ if (appid == _poi) {
+ m_start_flg.first = true;
+ set_destination2poi(api);
+ }
+ else if(appid == _navigation) {
+ m_start_flg.second = true;
+ start_navigation(api);
+ }
+ else {
+ AFB_WARNING("%s isn't interest app.", appid.c_str());
+ return;
+ }
+ }
+ if(m_start_flg.first && m_start_flg.second) {
+ HS_ClientManager::instance()->removeListener(this);
+ clearListenAppSet();
+ }
+}
+
+/**
+ * set destination to poiapp
+ *
+ * #### Parameters
+ * - api : the api
+ *
+ * #### Return
+ * None
+ *
+ */
+void Vui_Navigation::set_destination2poi(afb_api_t api)
+{
+ struct json_object *param = json_object_new_object();
+ json_object_object_add(param, _latitudeInDegrees, json_object_new_double(m_dest.first));
+ json_object_object_add(param, _longitudeInDegrees, json_object_new_double(m_dest.second));
+ HS_ClientManager::instance()->pushEvent(_setDestination, param);
+}
+
+/**
+ * set destination and start navigation
+ *
+ * #### Parameters
+ * - api : the ap
+ *
+ * #### Return
+ * None
+ *
+ */
+void Vui_Navigation::start_navigation(afb_api_t api)
+{
+ HS_ClientManager::instance()->pushEvent(_startNavigation, nullptr);
+}
+
+/* -------------------------------------HS_VuiAdapter------------------------------------------ */
+
+HS_VuiAdapter* HS_VuiAdapter::me = nullptr;
+
+/**
+ * get instance
+ *
+ * #### Parameters
+ * - Nothing
+ *
+ * #### Return
+ * HS_VuiAdapter instance pointer
+ *
+ */
+HS_VuiAdapter* HS_VuiAdapter::instance(void)
+{
+ if(me == nullptr)
+ me = new HS_VuiAdapter();
+
+ return me;
+}
+
+/**
+ * init
+ *
+ * #### Parameters
+ * - api : the api
+ *
+ * #### Return
+ * None
+ *
+ */
+void HS_VuiAdapter::init(afb_api_t api)
+{
+ std::string uid = std::string(_vui_prefixe) + std::string("-") + _navigation;
+ module_list[uid] = new Vui_Navigation(uid);
+
+ for(auto &it : module_list) {
+ it.second->init(api);
+ }
+}
+
+/**
+ * handle event
+ *
+ * #### Parameters
+ * - api : the api serving the request
+ * - event : event name
+ * - object : event json object
+ *
+ * #### Return
+ * 0 : continue transfer
+ * 1 : blocked
+ *
+ */
+int HS_VuiAdapter::onEvent(afb_api_t api, const char *event, struct json_object *object)
+{
+ for(auto &it : module_list) {
+ if(it.second->onEvent(api, event, object))
+ return 1;
+ }
+ return 0;
+}
\ No newline at end of file