// 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 <fidl/fuchsia.boot/cpp/wire.h>
#include <fidl/fuchsia.driver.index/cpp/wire.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/task.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/component/outgoing/cpp/outgoing_directory.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/io.h>
#include <lib/zx/event.h>
#include <lib/zx/port.h>
#include <lib/zx/resource.h>
#include <lib/zx/vmo.h>
#include <threads.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/object.h>
#include <zircon/syscalls/policy.h>
#include <zircon/types.h>

#include <cstdlib>
#include <cstring>
#include <limits>
#include <memory>

#include <fbl/unique_fd.h>

#include "src/devices/bin/driver_manager/devfs/devfs.h"
#include "src/devices/bin/driver_manager/driver_development/driver_development_service.h"
#include "src/devices/bin/driver_manager/driver_host_loader_service.h"
#include "src/devices/bin/driver_manager/driver_manager_config.h"
#include "src/devices/bin/driver_manager/driver_runner.h"
#include "src/devices/bin/driver_manager/shutdown/shutdown_manager.h"
#include "src/devices/lib/log/log.h"
#include "src/storage/lib/vfs/cpp/synchronous_vfs.h"
#include "src/sys/lib/stdout-to-debuglog/cpp/stdout-to-debuglog.h"

namespace fio = fuchsia_io;

namespace {
// Sets the logging process name. Needed to redirect output
// to serial.
void SetLoggingProcessName() {
  char process_name[ZX_MAX_NAME_LEN] = "";

  zx_status_t name_status =
      zx::process::self()->get_property(ZX_PROP_NAME, process_name, sizeof(process_name));
  if (name_status != ZX_OK) {
    process_name[0] = '\0';
  }
  driver_logger::GetLogger().AddTag(process_name);
}
}  // namespace

int main(int argc, char** argv) {
  zx_status_t status = StdoutToDebuglog::Init();
  if (status != ZX_OK) {
    LOGF(INFO, "Failed to redirect stdout to debuglog, assuming test environment and continuing");
  }

  auto config = driver_manager_config::Config::TakeFromStartupHandle();

  if (config.verbose()) {
    driver_logger::GetLogger().SetSeverity(std::numeric_limits<FuchsiaLogSeverity>::min());
  }

  SetLoggingProcessName();

  async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
  auto outgoing = component::OutgoingDirectory(loop.dispatcher());
  driver_manager::InspectManager inspect_manager(loop.dispatcher());

  // Launch DriverRunner for DFv2 drivers.
  auto realm_result = component::Connect<fuchsia_component::Realm>();
  if (realm_result.is_error()) {
    return realm_result.error_value();
  }
  auto driver_index_result = component::Connect<fuchsia_driver_index::DriverIndex>();
  if (driver_index_result.is_error()) {
    LOGF(ERROR, "Failed to connect to driver_index: %d", driver_index_result.error_value());
    return driver_index_result.error_value();
  }
  fbl::unique_fd lib_fd;
  constexpr uint32_t kOpenFlags = static_cast<uint32_t>(fio::wire::OpenFlags::kDirectory |
                                                        fio::wire::OpenFlags::kRightReadable |
                                                        fio::wire::OpenFlags::kRightExecutable);
  if (zx_status_t status = fdio_open_fd("/pkg/lib/", kOpenFlags, lib_fd.reset_and_get_address());
      status != ZX_OK) {
    LOGF(ERROR, "Failed to open /pkg/lib/ : %s", zx_status_get_string(status));
    return status;
  }
  // The loader needs its own thread because DriverManager makes synchronous calls to the
  // DriverHosts, which make synchronous calls to load their shared libraries.
  async::Loop loader_loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  loader_loop.StartThread("loader-loop");

  auto loader_service =
      driver_manager::DriverHostLoaderService::Create(loader_loop.dispatcher(), std::move(lib_fd));
  driver_manager::DriverRunner driver_runner(
      std::move(realm_result.value()), std::move(driver_index_result.value()), inspect_manager,
      [loader_service]() -> zx::result<fidl::ClientEnd<fuchsia_ldsvc::Loader>> {
        zx::result client = loader_service->Connect();
        if (client.is_error()) {
          return client.take_error();
        }
    // TODO(https://fxbug.dev/42076026): Find a better way to set this config.
#ifdef DRIVERHOST_LDSVC_CONFIG
        // Inform the loader service to look for libraries of the right variant.
        fidl::WireResult result = fidl::WireCall(client.value())->Config(DRIVERHOST_LDSVC_CONFIG);
        if (!result.ok()) {
          return zx::error(result.status());
        }
        if (result->rv != ZX_OK) {
          return zx::error(result->rv);
        }
#endif
        return client;
      },
      loop.dispatcher(), config.enable_test_shutdown_delays());

  // Setup devfs.
  std::optional<driver_manager::Devfs> devfs;
  driver_runner.root_node()->SetupDevfsForRootNode(devfs);
  driver_runner.PublishComponentRunner(outgoing);

  // Find and load v2 Drivers.
  LOGF(INFO, "Starting DriverRunner with root driver URL: %s", config.root_driver().c_str());
  if (auto start = driver_runner.StartRootDriver(config.root_driver()); start.is_error()) {
    return start.error_value();
  }

  driver_manager::DriverDevelopmentService driver_development_service(driver_runner,
                                                                      loop.dispatcher());
  driver_development_service.Publish(outgoing);
  driver_runner.ScheduleWatchForDriverLoad();

  driver_manager::ShutdownManager shutdown_manager(&driver_runner, loop.dispatcher());
  shutdown_manager.Publish(outgoing);

  // TODO(https://fxbug.dev/42181480) Remove this when this issue is fixed.
  LOGF(INFO, "driver_manager loader loop started");

  fs::SynchronousVfs vfs(loop.dispatcher());

  // Add the devfs folder to the tree:
  {
    zx::result devfs_client = devfs.value().Connect(vfs);
    ZX_ASSERT_MSG(devfs_client.is_ok(), "%s", devfs_client.status_string());
    const zx::result result = outgoing.AddDirectory(std::move(devfs_client.value()), "dev");
    ZX_ASSERT(result.is_ok());
  }

  {
    const zx::result result = outgoing.ServeFromStartupInfo();
    ZX_ASSERT_MSG(result.is_ok(), "%s", result.status_string());
  }

  async::PostTask(loop.dispatcher(), [] { LOGF(INFO, "driver_manager main loop is running"); });

  status = loop.Run();
  LOGF(ERROR, "Driver Manager exited unexpectedly: %s", zx_status_get_string(status));
  return status;
}
