// Copyright 2017 The Fuchsia 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 "peridot/bin/sessionmgr/component_context_impl.h"

#include <src/lib/fxl/logging.h>

#include <utility>

#include "peridot/bin/sessionmgr/agent_runner/agent_runner.h"
#include "peridot/lib/fidl/array_to_string.h"

namespace modular {

ComponentContextImpl::ComponentContextImpl(const ComponentContextInfo& info,
                                           std::string component_namespace,
                                           std::string component_instance_id,
                                           std::string component_url)
    : message_queue_manager_(info.message_queue_manager),
      agent_runner_(info.agent_runner),
      ledger_repository_(info.ledger_repository),
      entity_provider_runner_(info.entity_provider_runner),
      component_namespace_(std::move(component_namespace)),
      component_instance_id_(std::move(component_instance_id)),
      component_url_(std::move(component_url)) {
  FXL_DCHECK(message_queue_manager_);
  FXL_DCHECK(agent_runner_);
  FXL_DCHECK(ledger_repository_);
  FXL_DCHECK(entity_provider_runner_);
}

ComponentContextImpl::~ComponentContextImpl() = default;

void ComponentContextImpl::Connect(
    fidl::InterfaceRequest<fuchsia::modular::ComponentContext> request) {
  bindings_.AddBinding(this, std::move(request));
}

fuchsia::modular::ComponentContextPtr ComponentContextImpl::NewBinding() {
  fuchsia::modular::ComponentContextPtr ptr;
  Connect(ptr.NewRequest());
  return ptr;
}

void ComponentContextImpl::GetLedger(
    fidl::InterfaceRequest<fuchsia::ledger::Ledger> request) {
  ledger_repository_->GetLedger(to_array(component_url_), std::move(request));
}

void ComponentContextImpl::ConnectToAgent(
    std::string url,
    fidl::InterfaceRequest<fuchsia::sys::ServiceProvider>
        incoming_services_request,
    fidl::InterfaceRequest<fuchsia::modular::AgentController>
        agent_controller_request) {
  agent_runner_->ConnectToAgent(component_instance_id_, url,
                                std::move(incoming_services_request),
                                std::move(agent_controller_request));
}

void ComponentContextImpl::ConnectToAgentService(
    fuchsia::modular::AgentServiceRequest request) {
  agent_runner_->ConnectToAgentService(component_instance_id_,
                                       std::move(request));
}

void ComponentContextImpl::ObtainMessageQueue(
    std::string name,
    fidl::InterfaceRequest<fuchsia::modular::MessageQueue> request) {
  message_queue_manager_->ObtainMessageQueue(
      component_namespace_, component_instance_id_, name, std::move(request));
}

void ComponentContextImpl::DeleteMessageQueue(std::string name) {
  message_queue_manager_->DeleteMessageQueue(component_namespace_,
                                             component_instance_id_, name);
}

void ComponentContextImpl::GetMessageSender(
    std::string queue_token,
    fidl::InterfaceRequest<fuchsia::modular::MessageSender> request) {
  message_queue_manager_->GetMessageSender(queue_token, std::move(request));
}

void ComponentContextImpl::GetEntityResolver(
    fidl::InterfaceRequest<fuchsia::modular::EntityResolver> request) {
  entity_provider_runner_->ConnectEntityResolver(std::move(request));
}

void ComponentContextImpl::CreateEntityWithData(
    std::vector<fuchsia::modular::TypeToDataEntry> type_to_data,
    CreateEntityWithDataCallback result) {
  std::map<std::string, std::string> copy;
  for (const auto& it : type_to_data) {
    copy[it.type] = it.data;
  }
  result(entity_provider_runner_->CreateReferenceFromData(std::move(copy)));
}

void ComponentContextImpl::GetPackageName(GetPackageNameCallback result) {
  result(component_url_);
}

}  // namespace modular
