// Copyright 2016 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 "garnet/bin/appmgr/namespace.h"

#include <fuchsia/device/manager/cpp/fidl.h>
#include <fuchsia/kernel/cpp/fidl.h>
#include <fuchsia/process/cpp/fidl.h>
#include <fuchsia/scheduler/cpp/fidl.h>
#include <fuchsia/virtualconsole/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <trace/event.h>

#include <utility>

#include "garnet/bin/appmgr/job_provider_impl.h"
#include "garnet/bin/appmgr/realm.h"
#include "garnet/bin/appmgr/util.h"

namespace component {

Namespace::Namespace(fxl::RefPtr<Namespace> parent, Realm* realm,
                     fuchsia::sys::ServiceListPtr additional_services,
                     const std::vector<std::string>* service_whitelist)
    : vfs_(async_get_default_dispatcher()),
      services_(fbl::AdoptRef(new ServiceProviderDirImpl(service_whitelist))),
      job_provider_(fbl::AdoptRef(new JobProviderImpl(realm))),
      realm_(realm) {
  services_->AddService(
      fuchsia::sys::Environment::Name_,
      fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
        environment_bindings_.AddBinding(
            this, fidl::InterfaceRequest<fuchsia::sys::Environment>(
                      std::move(channel)));
        return ZX_OK;
      })));
  services_->AddService(
      Launcher::Name_,
      fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
        launcher_bindings_.AddBinding(
            this, fidl::InterfaceRequest<Launcher>(std::move(channel)));
        return ZX_OK;
      })));
  services_->AddService(
      fuchsia::process::Launcher::Name_,
      fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
        realm_->environment_services()->Connect(
            fidl::InterfaceRequest<fuchsia::process::Launcher>(
                std::move(channel)));
        return ZX_OK;
      })));
  services_->AddService(
      fuchsia::process::Resolver::Name_,
      fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
        resolver_bindings_.AddBinding(
            this, fidl::InterfaceRequest<fuchsia::process::Resolver>(
                      std::move(channel)));
        return ZX_OK;
      })));

  if (additional_services) {
    auto& names = additional_services->names;
    service_provider_ = additional_services->provider.Bind();
    service_host_directory_ = std::move(additional_services->host_directory);
    for (auto& name : names) {
      if (service_host_directory_) {
        services_->AddService(
            name,
            fbl::AdoptRef(new fs::Service([this, name](zx::channel channel) {
              fdio_service_connect_at(service_host_directory_.get(),
                                      name.c_str(), channel.release());
              return ZX_OK;
            })));
      } else {
        services_->AddService(
            name,
            fbl::AdoptRef(new fs::Service([this, name](zx::channel channel) {
              service_provider_->ConnectToService(name, std::move(channel));
              return ZX_OK;
            })));
      }
    }
  }

  // If any services in |parent| share a name with |additional_services|,
  // |additional_services| takes priority.
  if (parent) {
    services_->set_parent(parent->services());
  }

  // If any of these services aren't in additional_services or the parent
  // namespace, add them here directly. (AddService skips duplicate services)
  services_->AddService(
      fuchsia::scheduler::ProfileProvider::Name_,
      fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
        realm_->environment_services()->Connect(
            fidl::InterfaceRequest<fuchsia::scheduler::ProfileProvider>(
                std::move(channel)));
        return ZX_OK;
      })));
  services_->AddService(
      fuchsia::kernel::DebugBroker::Name_,
      fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
        realm_->environment_services()->Connect(
            fidl::InterfaceRequest<fuchsia::kernel::DebugBroker>(
                std::move(channel)));
        return ZX_OK;
      })));
  services_->AddService(
      fuchsia::device::manager::DebugDumper::Name_,
      fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
        realm_->environment_services()->Connect(
            fidl::InterfaceRequest<fuchsia::device::manager::DebugDumper>(
                std::move(channel)));
        return ZX_OK;
      })));
  services_->AddService(
      fuchsia::device::manager::Administrator::Name_,
      fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
        realm_->environment_services()->Connect(
            fidl::InterfaceRequest<fuchsia::device::manager::Administrator>(
                std::move(channel)));
        return ZX_OK;
      })));
  services_->AddService(
      fuchsia::virtualconsole::SessionManager::Name_,
      fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
        realm_->environment_services()->Connect(
            fidl::InterfaceRequest<fuchsia::virtualconsole::SessionManager>(
                std::move(channel)));
        return ZX_OK;
      })));
}

Namespace::~Namespace() {}

void Namespace::AddBinding(
    fidl::InterfaceRequest<fuchsia::sys::Environment> environment) {
  environment_bindings_.AddBinding(this, std::move(environment));
}

void Namespace::CreateNestedEnvironment(
    fidl::InterfaceRequest<fuchsia::sys::Environment> environment,
    fidl::InterfaceRequest<fuchsia::sys::EnvironmentController> controller,
    std::string label, fuchsia::sys::ServiceListPtr additional_services,
    fuchsia::sys::EnvironmentOptions options) {
  realm_->CreateNestedEnvironment(std::move(environment), std::move(controller),
                                  std::move(label),
                                  std::move(additional_services), options);
}

void Namespace::GetLauncher(fidl::InterfaceRequest<Launcher> launcher) {
  launcher_bindings_.AddBinding(this, std::move(launcher));
}

void Namespace::GetServices(
    fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) {
  services_->AddBinding(std::move(services));
}

zx_status_t Namespace::ServeServiceDirectory(zx::channel directory_request) {
  return vfs_.ServeDirectory(services_, std::move(directory_request));
}

void Namespace::CreateComponent(
    fuchsia::sys::LaunchInfo launch_info,
    fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
  auto cc_trace_id = TRACE_NONCE();
  TRACE_ASYNC_BEGIN("appmgr", "Namespace::CreateComponent", cc_trace_id,
                    "launch_info.url", launch_info.url);
  realm_->CreateComponent(
      std::move(launch_info), std::move(controller),
      [cc_trace_id](std::weak_ptr<ComponentControllerImpl> component) {
        TRACE_ASYNC_END("appmgr", "Namespace::CreateComponent", cc_trace_id);
      });
}

zx::channel Namespace::OpenServicesAsDirectory() {
  return Util::OpenAsDirectory(&vfs_, services_);
}

void Namespace::Resolve(std::string name,
                        fuchsia::process::Resolver::ResolveCallback callback) {
  realm_->Resolve(name, std::move(callback));
}

}  // namespace component
