// Copyright 2018 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 <lib/devmgr-launcher/launch.h>
#include <lib/devmgr-launcher/processargs.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/io.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/spawn.h>
#include <lib/zx/channel.h>
#include <lib/zx/process.h>
#include <stdint.h>
#include <zircon/assert.h>
#include <zircon/device/vfs.h>
#include <zircon/processargs.h>
#include <zircon/status.h>

#include <utility>

#include <fbl/algorithm.h>

namespace {

constexpr const char* kDevmgrPath = "/boot/bin/devcoordinator";

}  // namespace

namespace devmgr_launcher {

__EXPORT
zx_status_t Launch(Args args, zx::channel svc_client, zx::job* devmgr_job, zx::channel* devfs_root,
                   zx::channel* outgoing_services_root) {
  // Create containing job (and copy to send to devmgr)
  zx::job job, job_copy;
  zx_status_t status = zx::job::create(*zx::job::default_job(), 0, &job);
  if (status != ZX_OK) {
    return status;
  }
  status = job.duplicate(ZX_RIGHT_SAME_RIGHTS, &job_copy);
  if (status != ZX_OK) {
    return status;
  }

  // Create channel to connect to devfs
  zx::channel devfs_client, devfs_server;
  status = zx::channel::create(0, &devfs_client, &devfs_server);
  if (status != ZX_OK) {
    return status;
  }

  // Create channel to connect to outgoing services
  zx::channel outgoing_services_client, outgoing_services_server;
  status = zx::channel::create(0, &outgoing_services_client, &outgoing_services_server);
  if (status != ZX_OK) {
    return status;
  }

  const bool clone_stdio = !args.stdio.is_valid();

  fbl::Vector<const char*> argv;
  argv.push_back(kDevmgrPath);
  argv.push_back("--no-start-svchost");
  for (const char* path : args.driver_search_paths) {
    argv.push_back("--driver-search-path");
    argv.push_back(path);
  }
  for (const char* path : args.load_drivers) {
    argv.push_back("--load-driver");
    argv.push_back(path);
  }
  if (args.sys_device_driver != nullptr) {
    argv.push_back("--sys-device-driver");
    argv.push_back(args.sys_device_driver);
  }
  if (args.disable_block_watcher) {
    argv.push_back("--disable-block-watcher");
  }
  if (args.disable_netsvc) {
    argv.push_back("--disable-netsvc");
  }
  argv.push_back(nullptr);

  fbl::Vector<fdio_spawn_action_t> actions;
  actions.push_back(fdio_spawn_action_t{
      .action = FDIO_SPAWN_ACTION_SET_NAME,
      .name = {.data = "test-devmgr"},
  });
  actions.push_back(fdio_spawn_action_t{
      .action = FDIO_SPAWN_ACTION_ADD_HANDLE,
      .h = {.id = PA_HND(PA_JOB_DEFAULT, 0), .handle = job_copy.release()},
  });
  actions.push_back(fdio_spawn_action_t{
      .action = FDIO_SPAWN_ACTION_ADD_HANDLE,
      .h = {.id = DEVMGR_LAUNCHER_DEVFS_ROOT_HND, .handle = devfs_server.release()},
  });
  actions.push_back(fdio_spawn_action_t{
      .action = FDIO_SPAWN_ACTION_ADD_HANDLE,
      .h = {.id = DEVMGR_LAUNCHER_OUTGOING_SERVICES_HND,
            .handle = outgoing_services_server.release()},
  });

  for (auto& ns : args.flat_namespace) {
    actions.push_back(fdio_spawn_action_t{
        .action = FDIO_SPAWN_ACTION_ADD_NS_ENTRY,
        .ns = {.prefix = ns.first, .handle = ns.second.release()},
    });
  }

  actions.push_back(fdio_spawn_action_t{
      .action = FDIO_SPAWN_ACTION_CLONE_DIR,
      .dir = {.prefix = "/boot"},
  });

  actions.push_back(fdio_spawn_action_t{
      .action = FDIO_SPAWN_ACTION_ADD_NS_ENTRY,
      .ns = {.prefix = "/svc", .handle = svc_client.release()},
  });

  if (!clone_stdio) {
    actions.push_back(fdio_spawn_action_t{
        .action = FDIO_SPAWN_ACTION_TRANSFER_FD,
        .fd = {.local_fd = args.stdio.release(), .target_fd = FDIO_FLAG_USE_FOR_STDIO},
    });
  }

  uint32_t flags = FDIO_SPAWN_DEFAULT_LDSVC;
  if (clone_stdio) {
    flags |= FDIO_SPAWN_CLONE_STDIO;
  }

  zx::process new_process;
  status = fdio_spawn_etc(job.get(), flags, kDevmgrPath, argv.data(), nullptr /* environ */,
                          actions.size(), actions.data(), new_process.reset_and_get_address(),
                          nullptr /* err_msg */);
  if (status != ZX_OK) {
    return status;
  }

  *devmgr_job = std::move(job);
  *devfs_root = std::move(devfs_client);
  *outgoing_services_root = std::move(outgoing_services_client);
  return ZX_OK;
}

}  // namespace devmgr_launcher
