

#include "vehicle_info_plugin/commands/mobile/diagnostic_message_request.h"
#include <algorithm>

#include "application_manager/application_impl.h"

#include "application_manager/message_helper.h"
#include "interfaces/HMI_API.h"

namespace vehicle_info_plugin {
using namespace application_manager;

namespace commands {

SDL_CREATE_LOG_VARIABLE("Commands")

DiagnosticMessageRequest::DiagnosticMessageRequest(
    const application_manager::commands::MessageSharedPtr& message,
    const VehicleInfoCommandParams& params)
    : RequestFromMobileImpl(message,
                            params.application_manager_,
                            params.rpc_service_,
                            params.hmi_capabilities_,
                            params.policy_handler_) {}

DiagnosticMessageRequest::~DiagnosticMessageRequest() {}

void DiagnosticMessageRequest::Run() {
  SDL_LOG_AUTO_TRACE();

  ApplicationSharedPtr app = application_manager_.application(connection_key());

  if (!app) {
    SDL_LOG_ERROR("Application is not registered.");
    SendResponse(false, mobile_apis::Result::APPLICATION_NOT_REGISTERED);
    return;
  }

  const std::vector<uint32_t>& supported_diag_modes =
      application_manager_.get_settings().supported_diag_modes();

  smart_objects::SmartObject& msg_data =
      (*message_)[strings::msg_params][strings::message_data];

  const uint8_t mode_position = 0;
  const uint32_t msg_diagnostic_mode = msg_data[mode_position].asUInt();
  if (supported_diag_modes.end() == std::find(supported_diag_modes.begin(),
                                              supported_diag_modes.end(),
                                              msg_diagnostic_mode)) {
    SDL_LOG_ERROR("Received diagnostic mode " << msg_diagnostic_mode
                                              << " is not supported.");
    SendResponse(false,
                 mobile_apis::Result::REJECTED,
                 "Received diagnostic mode is not supported.");
    return;
  }

  // Add app_id for HMI request
  (*message_)[strings::msg_params][strings::app_id] = app->app_id();

  StartAwaitForInterface(HmiInterfaces::HMI_INTERFACE_VehicleInfo);
  SendHMIRequest(hmi_apis::FunctionID::VehicleInfo_DiagnosticMessage,
                 &(*message_)[strings::msg_params],
                 true);
}

void DiagnosticMessageRequest::on_event(const event_engine::Event& event) {
  SDL_LOG_AUTO_TRACE();
  const smart_objects::SmartObject& message = event.smart_object();

  switch (event.id()) {
    case hmi_apis::FunctionID::VehicleInfo_DiagnosticMessage: {
      EndAwaitForInterface(HmiInterfaces::HMI_INTERFACE_VehicleInfo);
      hmi_apis::Common_Result::eType result_code =
          static_cast<hmi_apis::Common_Result::eType>(
              message[strings::params][hmi_response::code].asInt());
      const bool result = PrepareResultForMobileResponse(
          result_code, HmiInterfaces::HMI_INTERFACE_VehicleInfo);
      std::string response_info;
      GetInfo(message, response_info);
      SendResponse(result,
                   MessageHelper::HMIToMobileResult(result_code),
                   response_info.empty() ? NULL : response_info.c_str(),
                   &(message[strings::msg_params]));
      break;
    }
    default: {
      SDL_LOG_ERROR("Received unknown event " << event.id());
      return;
    }
  }
}

}  // namespace commands

}  // namespace vehicle_info_plugin
