// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/functional/bind.h>
#include <base/json/json_writer.h>
#include <base/logging.h>
#include <base/task/single_thread_task_runner.h>
#include <base/values.h>
#include <dbus/runtime_probe/dbus-constants.h>
#include <google/protobuf/util/json_util.h>
#include <mojo/core/embedder/embedder.h>
#include <mojo/core/embedder/scoped_ipc_support.h>

#include "runtime_probe/avl_probe_config_loader.h"
#include "runtime_probe/daemon.h"
#include "runtime_probe/probe_config.h"
#include "runtime_probe/proto_bindings/runtime_probe.pb.h"
#include "runtime_probe/ssfc_probe_config_loader.h"

namespace runtime_probe {

namespace {

using brillo::dbus_utils::AsyncEventSequencer;
using brillo::dbus_utils::DBusObject;

}  // namespace

Daemon::Daemon()
    : brillo::DBusServiceDaemon(kRuntimeProbeServiceName),
      org::chromium::RuntimeProbeAdaptor(this) {}

int Daemon::OnInit() {
  VLOG(1) << "Starting D-Bus service";
  const auto exit_code = brillo::DBusServiceDaemon::OnInit();

  // Required by mojo
  mojo::core::Init();
  ipc_support_ = std::make_unique<mojo::core::ScopedIPCSupport>(
      base::SingleThreadTaskRunner::GetCurrentDefault(),
      mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);

  return exit_code;
}

void Daemon::RegisterDBusObjectsAsync(AsyncEventSequencer* sequencer) {
  DCHECK(!dbus_object_);
  dbus_object_ = std::make_unique<brillo::dbus_utils::DBusObject>(
      nullptr, bus_, dbus::ObjectPath(kRuntimeProbeServicePath));
  RegisterWithDBusObject(dbus_object_.get());
  dbus_object_->RegisterAsync(
      sequencer->GetHandler("RegisterAsync() failed", true));
}

void Daemon::ProbeCategories(Daemon::DBusCallback<ProbeResult> cb,
                             const ProbeRequest& request) {
  AvlProbeConfigLoader config_loader;
  auto probe_config = config_loader.Load();
  if (!probe_config) {
    ProbeResult reply;
    reply.set_error(RUNTIME_PROBE_ERROR_PROBE_CONFIG_INVALID);
    cb->Return(reply);
    return Quit();
  }

  auto* probe_config_ptr = probe_config.get();
  if (request.probe_default_category()) {
    probe_config_ptr->Eval(base::BindOnce(&Daemon::ProbeCallback<ProbeResult>,
                                          base::Unretained(this), std::move(cb),
                                          std::move(probe_config)));
  } else {
    // Convert the ProbeReuslt from enum into array of string.
    std::vector<std::string> categories_to_probe;
    const google::protobuf::EnumDescriptor* descriptor =
        ProbeRequest_SupportCategory_descriptor();

    for (int j = 0; j < request.categories_size(); j++)
      categories_to_probe.push_back(
          descriptor->FindValueByNumber(request.categories(j))->name());
    probe_config_ptr->Eval(categories_to_probe,
                           base::BindOnce(&Daemon::ProbeCallback<ProbeResult>,
                                          base::Unretained(this), std::move(cb),
                                          std::move(probe_config)));
  }
}

void Daemon::GetKnownComponents(
    Daemon::DBusCallback<GetKnownComponentsResult> cb,
    const GetKnownComponentsRequest& request) {
  GetKnownComponentsResult reply;

  AvlProbeConfigLoader config_loader;
  const auto probe_config = config_loader.Load();
  if (!probe_config) {
    reply.set_error(RUNTIME_PROBE_ERROR_PROBE_CONFIG_INVALID);
    cb->Return(reply);
    return Quit();
  }

  std::string category_name =
      ProbeRequest_SupportCategory_Name(request.category());
  if (auto category = probe_config->GetComponentCategory(category_name);
      category != nullptr) {
    for (const auto& name : category->GetComponentNames()) {
      reply.add_component_names(name);
    }
  }

  cb->Return(reply);
  return Quit();
}

void Daemon::ProbeSsfcComponents(
    Daemon::DBusCallback<ProbeSsfcComponentsResponse> cb,
    const ProbeSsfcComponentsRequest& request) {
  SsfcProbeConfigLoader config_loader;
  auto probe_config = config_loader.Load();
  if (!probe_config) {
    ProbeSsfcComponentsResponse reply;
    reply.set_error(RUNTIME_PROBE_ERROR_PROBE_CONFIG_INVALID);
    cb->Return(reply);
    return Quit();
  }

  auto* probe_config_ptr = probe_config.get();
  probe_config_ptr->Eval(base::BindOnce(
      &Daemon::ProbeCallback<ProbeSsfcComponentsResponse>,
      base::Unretained(this), std::move(cb), std::move(probe_config)));
}

template <typename MessageType>
void Daemon::ProbeCallback(Daemon::DBusCallback<MessageType> cb,
                           std::unique_ptr<ProbeConfig> probe_config,
                           base::Value::Dict probe_result) {
  std::string output_json;
  base::JSONWriter::Write(probe_result, &output_json);
  DVLOG(3) << "Raw JSON probe result\n" << output_json;

  // Convert JSON to Protocol Buffer.
  MessageType reply;
  auto options = google::protobuf::util::JsonParseOptions();
  options.ignore_unknown_fields = true;
  const auto json_parse_status =
      google::protobuf::util::JsonStringToMessage(output_json, &reply, options);

  VLOG(3) << "serialize JSON to Protobuf status: " << json_parse_status;
  if (!json_parse_status.ok()) {
    reply.set_error(RUNTIME_PROBE_ERROR_PROBE_RESULT_INVALID);
  }

  cb->Return(reply);
  return Quit();
}

}  // namespace runtime_probe
