// 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 <dirent.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/directory.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/syslog/global.h>
#include <lib/trace-provider/provider.h>
#include <zircon/process.h>
#include <zircon/processargs.h>

#include <src/lib/files/directory.h>

#include "src/lib/fxl/command_line.h"
#include "src/sys/appmgr/appmgr.h"
#include "src/sys/appmgr/moniker.h"
#include "src/sys/lib/stdout-to-debuglog/cpp/stdout-to-debuglog.h"

namespace {

// Returns the set of service names that should be proxied to the root realm
// from appmgr's namespace
std::vector<std::string> RootRealmServices() {
  std::vector<std::string> res;
  bool success = files::ReadDirContents("/svc_for_sys", &res);
  if (!success) {
    FX_LOGS(WARNING) << "failed to read /svc_for_sys (" << errno
                     << "), not forwarding services to sys realm";
    return std::vector<std::string>();
  }
  return res;
}

// Creates a zircon socket and sets it to appmgr's stdin.
zx_status_t InitStdinSocket() {
  zx::socket reader, writer;
  // Create a socket pair for stdin. We'll just discard the writer so stdin always looks like it's
  // closed.
  zx_status_t status = zx::socket::create(0, &writer, &reader);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to create stdin socket: " << zx_status_get_string(status);
    return status;
  }
  status = reader.replace(ZX_RIGHTS_BASIC | ZX_RIGHT_READ, &reader);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to replace stdin reader: " << zx_status_get_string(status);
    return status;
  }
  fdio_t* io;
  status = fdio_create(reader.release(), &io);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to create fdio struct for stdin reader: "
                   << zx_status_get_string(status);
  }
  int fd = fdio_bind_to_fd(io, STDIN_FILENO, STDIN_FILENO);
  if (fd != STDIN_FILENO) {
    FX_LOGS(ERROR) << "failed to bind socket to stdin";
    return ZX_ERR_BAD_STATE;
  }

  return ZX_OK;
}

}  // namespace

int main(int argc, char** argv) {
  // Appmgr can't connect to the logging service just yet. Fall back to stderr to not lose any logs
  // in the meantime.
  fx_logger_activate_fallback(fx_log_get_logger(), -1);

  // Wire up standard streams. This sends all stdout and stderr to the debuglog.
  // This is necessary, instead of using fuchsia.logger.LogSink, because we need
  // to get appmgr logs before v1 components are running.
  zx_status_t status = StdoutToDebuglog::Init();
  if (status != ZX_OK) {
    return status;
  }

  status = InitStdinSocket();
  if (status != ZX_OK) {
    return status;
  }

  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  auto pa_directory_request = zx_take_startup_handle(PA_DIRECTORY_REQUEST);

  zx::channel svc_for_sys_server, svc_for_sys_client;
  status = zx::channel::create(0, &svc_for_sys_server, &svc_for_sys_client);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to create channel: " << zx_status_get_string(status);
    return status;
  }
  status =
      fdio_open("/svc_for_sys", ZX_FS_RIGHT_READABLE | ZX_FS_FLAG_DIRECTORY | ZX_FS_RIGHT_WRITABLE,
                svc_for_sys_server.release());
  if (status != ZX_OK) {
    FX_LOGS(WARNING) << "failed to open /svc_for_sys (" << zx_status_get_string(status)
                     << "), not forwarding services to sys realm";
    return status;
  }

  auto environment_services =
      std::make_shared<sys::ServiceDirectory>(std::move(svc_for_sys_client));

  // Certain services in appmgr's /svc, which is served by svchost, are added to
  // the root realm so they can be routed into a nested environment (such as the
  // sys realm in sysmgr) and used in components.
  fuchsia::sys::ServiceListPtr root_realm_services(new fuchsia::sys::ServiceList);
  root_realm_services->names = RootRealmServices();
  root_realm_services->host_directory = environment_services->CloneChannel().TakeChannel();

  zx::channel trace_client, trace_server;
  status = zx::channel::create(0, &trace_client, &trace_server);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to create tracing channel: " << status;
    return status;
  }

  trace::TraceProvider trace_provider(std::move(trace_client), loop.dispatcher());

  auto lifecycle_request = zx_take_startup_handle(PA_LIFECYCLE);
  std::unordered_set<component::Moniker> lifecycle_allowlist;
  lifecycle_allowlist.insert(component::Moniker{
      .url = "fuchsia-pkg://fuchsia.com/basemgr#meta/basemgr.cmx", .realm_path = {"app", "sys"}});
  lifecycle_allowlist.insert(component::Moniker{
      .url = "fuchsia-pkg://fuchsia.com/cobalt#meta/cobalt.cmx", .realm_path = {"app", "sys"}});
  lifecycle_allowlist.insert(
      component::Moniker{.url = "fuchsia-pkg://fuchsia.com/forensics#meta/crash_reports.cmx",
                         .realm_path = {"app", "sys"}});
  lifecycle_allowlist.insert(
      component::Moniker{.url = "fuchsia-pkg://fuchsia.com/forensics#meta/feedback_data.cmx",
                         .realm_path = {"app", "sys"}});

  component::AppmgrArgs args{.pa_directory_request = std::move(pa_directory_request),
                             .lifecycle_request = std::move(lifecycle_request),
                             .lifecycle_allowlist = std::move(lifecycle_allowlist),
                             .root_realm_services = std::move(root_realm_services),
                             .environment_services = std::move(environment_services),
                             .sysmgr_url = "fuchsia-pkg://fuchsia.com/sysmgr#meta/sysmgr.cmx",
                             .sysmgr_args = {},
                             .run_virtual_console = true,
                             .trace_server_channel = std::move(trace_server),
                             .stop_callback = [](zx_status_t status) { exit(status); }};
  component::Appmgr appmgr(loop.dispatcher(), std::move(args));

  loop.Run();
  return 0;
}
