// Copyright 2019 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 <fcntl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/directory.h>
#include <lib/sys/cpp/component_context.h>
#include <zircon/device/vfs.h>

#include <iostream>

#include "isolated_devmgr.h"
#include "src/lib/fxl/command_line.h"
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/strings/split_string.h"
#include "src/lib/fxl/strings/string_number_conversions.h"
#include "src/lib/fxl/strings/string_view.h"

#define DEVICE_IDS_VID_LOC 0
#define DEVICE_IDS_PID_LOC 1
#define DEVICE_IDS_DID_LOC 2
#define DEVICE_IDS_SIZE 3
#define ISO_DEV_MGR_RET_OK 0
#define ISO_DEV_MGR_RET_ERR 1

using namespace isolated_devmgr;

void Usage() {
  std::cerr <<
      R"(
Usage:
   isolated_devmgr [options]

Options:
   --svc_name=[svc_name]: service name to expose, defaults to fuchsia.io.Directory
   --load_driver=[driver_path]: loads a driver into isolated manager. May be informed multiple
                                times.
   --search_driver=[search_path]: loads all drivers in provided search path. May be informed
                                  multiple times.
   --sys_device=[sys_device_driver]: path to sys device driver, defaults to
                                     /boot/driver/test/sysdev.so
   --wait_for=[device]: wait for isolated manager to have |device| exposed before serving any
                        requests. May be informed multiple times.
   --add_namespace=[ns]: make the namespace 'ns' from this component available to the devmgr
                         under the same path.
   --device_vid_pid_did=[dev_vid:dev_pid:dev_did]: adding a device with hex dev_vid, dev_pid
                                                   and dev_did. May be informed multiple times.
   --help: displays this help page.

Note: isolated_devmgr runs as a component, so all paths must be relative to the component's
namespace. Since the devmgr libraries and executables are currently under /boot, the components
sandbox metadata must include the "/boot/bin" and "/boot/lib". Additionally, it's common to load
drivers out of "/boot/driver" and this directory must also be specificed in the components sandbox
metadata to make these drivers available to isolated_devmgr.

Example sandbox metadata:

    "sandbox": {
        "boot": [
            "bin",
            "driver",
            "lib"
        ]
    }
)";
}

static int process_device_ids(const char* str,
                              fbl::Vector<board_test::DeviceEntry>* dev_entry_list_ptr) {
  board_test::DeviceEntry dev_entry = {};
  uint32_t key;
  fxl::StringView sv_str = fxl::StringView(str);
  auto params = fxl::SplitString(sv_str, ":", fxl::kKeepWhitespace, fxl::kSplitWantNonEmpty);
  if ((dev_entry_list_ptr == nullptr) || (params.size() < DEVICE_IDS_SIZE)) {
    return ISO_DEV_MGR_RET_ERR;
  }
  if (!fxl::StringToNumberWithError(params.at(DEVICE_IDS_VID_LOC), &key, fxl::Base::k16)) {
    return ISO_DEV_MGR_RET_ERR;
  }
  dev_entry.vid = key;
  if (!fxl::StringToNumberWithError(params.at(DEVICE_IDS_PID_LOC), &key, fxl::Base::k16)) {
    return ISO_DEV_MGR_RET_ERR;
  }
  dev_entry.pid = key;
  if (!fxl::StringToNumberWithError(params.at(DEVICE_IDS_DID_LOC), &key, fxl::Base::k16)) {
    return ISO_DEV_MGR_RET_ERR;
  }
  dev_entry.did = key;
  dev_entry_list_ptr->push_back(dev_entry);
  return ISO_DEV_MGR_RET_OK;
}

int main(int argc, const char** argv) {
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  devmgr_launcher::Args args;
  auto device_list_unique_ptr = std::unique_ptr<fbl::Vector<board_test::DeviceEntry>>(
      new fbl::Vector<board_test::DeviceEntry>());

  // fill up defaults:
  args.sys_device_driver = "/boot/driver/test/sysdev.so";
  args.stdio = fbl::unique_fd(open("/dev/null", O_RDWR));
  args.disable_block_watcher = true;
  args.disable_netsvc = true;

  std::string svc_name = "fuchsia.io.Directory";
  std::vector<std::string> wait;
  std::vector<std::string> namespaces;

  // load options from command line
  auto cl = fxl::CommandLineFromArgcArgv(argc, argv);
  for (const auto& opt : cl.options()) {
    if (opt.name == "svc_name") {
      svc_name = opt.value;
    } else if (opt.name == "load_driver") {
      args.load_drivers.push_back(opt.value.c_str());
    } else if (opt.name == "search_driver") {
      args.driver_search_paths.push_back(opt.value.c_str());
    } else if (opt.name == "sys_device") {
      args.sys_device_driver = opt.value.c_str();
    } else if (opt.name == "wait_for") {
      wait.push_back(opt.value);
    } else if (opt.name == "add_namespace") {
      namespaces.push_back(opt.value);
    } else if (opt.name == "device_vid_pid_did") {
      int status = process_device_ids(opt.value.c_str(), device_list_unique_ptr.get());
      if (status != 0) {
        Usage();
        return status;
      }
    } else if (opt.name == "help") {
      Usage();
      return ISO_DEV_MGR_RET_OK;
    } else {
      Usage();
      return ISO_DEV_MGR_RET_ERR;
    }
  }

  // Pass-through any additional namespaces that we want to provide to the devmgr. These are
  // exposed to devmgr under the same local path. Ex: if you share '/pkg', you could provide a
  // driver as '/pkg/data/my_driver.so'.
  for (const auto& ns : namespaces) {
    zx::channel client, server;
    zx_status_t status = zx::channel::create(0, &client, &server);
    if (status != ZX_OK) {
      FX_PLOGS(ERROR, status) << "Failed to create channel";
      return ISO_DEV_MGR_RET_ERR;
    }
    status = fdio_open(ns.c_str(), ZX_FS_RIGHT_READABLE, server.release());
    if (status != ZX_OK) {
      FX_PLOGS(ERROR, status) << "Failed to open namespace " << ns;
      return ISO_DEV_MGR_RET_ERR;
    }
    args.flat_namespace.push_back({ns.c_str(), std::move(client)});
  }

  auto devmgr =
      IsolatedDevmgr::Create(std::move(args), std::move(device_list_unique_ptr), loop.dispatcher());
  if (!devmgr) {
    return ISO_DEV_MGR_RET_ERR;
  }

  devmgr->SetExceptionCallback([]() {
    FX_LOGS(ERROR) << "Isolated Devmgr crashed";
    zx_process_exit(ISO_DEV_MGR_RET_ERR);
  });

  for (const auto& path : wait) {
    if (devmgr->WaitForFile(path.c_str()) != ZX_OK) {
      FX_LOGS(ERROR) << "Isolated Devmgr failed while waiting for path " << path;
      return ISO_DEV_MGR_RET_ERR;
    }
  }

  auto context = sys::ComponentContext::CreateAndServeOutgoingDirectory();
  auto service =
      std::make_unique<vfs::Service>([&devmgr](zx::channel chan, async_dispatcher_t* dispatcher) {
        devmgr->Connect(std::move(chan));
      });
  context->outgoing()->AddPublicService(std::move(service), std::move(svc_name));

  loop.Run();

  return ISO_DEV_MGR_RET_OK;
}
