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

#include "diagnostics/wilco_dtc_supportd/mojo_service.h"

#include <memory>
#include <utility>

#include <base/logging.h>

#include "diagnostics/common/mojo_utils.h"
#include "diagnostics/wilco_dtc_supportd/json_utils.h"

namespace diagnostics {

using SendUiMessageToWilcoDtcCallback =
    MojoService::SendUiMessageToWilcoDtcCallback;

namespace {

void ForwardMojoJsonResponse(
    SendUiMessageToWilcoDtcCallback mojo_response_callback,
    std::string response_json_message) {
  if (response_json_message.empty()) {
    std::move(mojo_response_callback)
        .Run(mojo::ScopedHandle() /* response_json_message */);
    return;
  }
  mojo::ScopedHandle response_json_message_handle =
      CreateReadOnlySharedMemoryRegionMojoHandle(
          base::StringPiece(response_json_message));
  std::move(mojo_response_callback)
      .Run(std::move(response_json_message_handle));
}

void ForwardMojoSendtoUiResponse(
    const MojoService::MojomSendWilcoDtcMessageToUiCallback& callback,
    mojo::ScopedHandle response_body_handle) {
  auto shm_mapping = GetReadOnlySharedMemoryMappingFromMojoHandle(
      std::move(response_body_handle));
  if (!shm_mapping.IsValid()) {
    LOG(ERROR) << "Failed to read data from mojo handle";
    callback.Run(grpc::Status(grpc::StatusCode::UNKNOWN,
                              "Failed to read data from mojo handle"),
                 base::StringPiece());
    return;
  }
  callback.Run(grpc::Status::OK,
               base::StringPiece(shm_mapping.GetMemoryAs<const char>(),
                                 shm_mapping.mapped_size()));
}

void ForwardMojoWebResponse(
    const MojoService::MojomPerformWebRequestCallback& callback,
    MojoService::MojomWilcoDtcSupportdWebRequestStatus status,
    int http_status,
    mojo::ScopedHandle response_body_handle) {
  if (!response_body_handle.is_valid()) {
    callback.Run(status, http_status, base::StringPiece());
    return;
  }
  auto shm_mapping = GetReadOnlySharedMemoryMappingFromMojoHandle(
      std::move(response_body_handle));
  if (!shm_mapping.IsValid()) {
    LOG(ERROR) << "Failed to read data from mojo handle";
    callback.Run(
        MojoService::MojomWilcoDtcSupportdWebRequestStatus::kNetworkError, 0,
        base::StringPiece());
    return;
  }
  callback.Run(status, http_status,
               base::StringPiece(shm_mapping.GetMemoryAs<const char>(),
                                 shm_mapping.mapped_size()));
}

}  // namespace

MojoService::MojoService(
    MojoGrpcAdapter* grpc_adapter,
    MojomWilcoDtcSupportdServiceRequest self_interface_request,
    MojomWilcoDtcSupportdClientPtr client_ptr)
    : grpc_adapter_(grpc_adapter),
      self_binding_(this /* impl */, std::move(self_interface_request)),
      client_ptr_(std::move(client_ptr)) {
  DCHECK(self_binding_.is_bound());
  DCHECK(grpc_adapter_);
  DCHECK(client_ptr_);
}

MojoService::~MojoService() = default;

void MojoService::SendUiMessageToWilcoDtc(
    mojo::ScopedHandle json_message, SendUiMessageToWilcoDtcCallback callback) {
  auto shm_mapping =
      GetReadOnlySharedMemoryMappingFromMojoHandle(std::move(json_message));
  if (!shm_mapping.IsValid()) {
    LOG(ERROR) << "Failed to read data from mojo handle";
    std::move(callback).Run(mojo::ScopedHandle() /* response_json_message */);
    return;
  }
  base::StringPiece json_message_content(shm_mapping.GetMemoryAs<const char>(),
                                         shm_mapping.mapped_size());

  std::string json_error_message;
  if (!IsJsonValid(json_message_content, &json_error_message)) {
    LOG(ERROR) << "Invalid JSON error: " << json_error_message;
    std::move(callback).Run(mojo::ScopedHandle() /* response_json_message */);
    return;
  }

  grpc_adapter_->SendGrpcUiMessageToWilcoDtc(
      json_message_content,
      base::Bind(&ForwardMojoJsonResponse, base::Passed(std::move(callback))));
}

void MojoService::NotifyConfigurationDataChanged() {
  grpc_adapter_->NotifyConfigurationDataChangedToWilcoDtc();
}

void MojoService::SendWilcoDtcMessageToUi(
    const std::string& json_message,
    const MojomSendWilcoDtcMessageToUiCallback& callback) {
  VLOG(1) << "SendWilcoDtcMessageToUi json_message=" << json_message;
  mojo::ScopedHandle json_message_mojo_handle =
      CreateReadOnlySharedMemoryRegionMojoHandle(json_message);
  if (!json_message_mojo_handle.is_valid()) {
    LOG(ERROR) << "Failed to create a mojo handle.";
    callback.Run(grpc::Status(grpc::StatusCode::UNKNOWN,
                              "Failed to read data from mojo handle"),
                 base::StringPiece());
    return;
  }

  client_ptr_->SendWilcoDtcMessageToUi(
      std::move(json_message_mojo_handle),
      base::Bind(&ForwardMojoSendtoUiResponse, callback));
}

void MojoService::PerformWebRequest(
    MojomWilcoDtcSupportdWebRequestHttpMethod http_method,
    const std::string& url,
    const std::vector<std::string>& headers,
    const std::string& request_body,
    const MojomPerformWebRequestCallback& callback) {
  DCHECK(client_ptr_);
  mojo::ScopedHandle url_handle =
      CreateReadOnlySharedMemoryRegionMojoHandle(url);
  if (!url_handle.is_valid()) {
    LOG(ERROR) << "Failed to create a mojo handle.";
    callback.Run(MojomWilcoDtcSupportdWebRequestStatus::kNetworkError, 0,
                 base::StringPiece());
    return;
  }

  std::vector<mojo::ScopedHandle> header_handles;
  for (const auto& header : headers) {
    header_handles.push_back(
        CreateReadOnlySharedMemoryRegionMojoHandle(header));
    if (!header_handles.back().is_valid()) {
      LOG(ERROR) << "Failed to create a mojo handle.";
      callback.Run(MojomWilcoDtcSupportdWebRequestStatus::kNetworkError, 0,
                   base::StringPiece());
      return;
    }
  }
  mojo::ScopedHandle request_body_handle =
      CreateReadOnlySharedMemoryRegionMojoHandle(request_body);
  // Invalid handle for an empty |request_body| does not cause an error.
  if (!request_body.empty() && !request_body_handle.is_valid()) {
    LOG(ERROR) << "Failed to create a mojo handle.";
    callback.Run(MojomWilcoDtcSupportdWebRequestStatus::kNetworkError, 0,
                 base::StringPiece());
    return;
  }

  client_ptr_->PerformWebRequest(http_method, std::move(url_handle),
                                 std::move(header_handles),
                                 std::move(request_body_handle),
                                 base::Bind(&ForwardMojoWebResponse, callback));
}

void MojoService::GetConfigurationData(
    MojomGetConfigurationDataCallback callback) {
  DCHECK(client_ptr_);
  client_ptr_->GetConfigurationData(std::move(callback));
}

void MojoService::HandleEvent(const MojomWilcoDtcSupportdEvent event) {
  client_ptr_->HandleEvent(event);
}

void MojoService::GetCrosHealthdDiagnosticsService(
    chromeos::cros_healthd::mojom::CrosHealthdDiagnosticsServiceRequest
        service) {
  client_ptr_->GetCrosHealthdDiagnosticsService(std::move(service));
}

void MojoService::GetCrosHealthdProbeService(
    chromeos::cros_healthd::mojom::CrosHealthdProbeServiceRequest service) {
  client_ptr_->GetCrosHealthdProbeService(std::move(service));
}

}  // namespace diagnostics
