// 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 <fuchsia/modular/internal/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/directory.h>
#include <lib/fit/result.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/log_settings.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/vfs/cpp/pseudo_dir.h>
#include <lib/vfs/cpp/pseudo_file.h>

#include <iostream>
#include <regex>

#include <src/lib/files/glob.h>
#include <src/lib/fxl/command_line.h>
#include <src/modular/lib/modular_config/modular_config.h>
#include <src/modular/lib/modular_config/modular_config_constants.h>
#include <zxtest/zxtest.h>

constexpr char kBasemgrUrl[] = "fuchsia-pkg://fuchsia.com/basemgr#meta/basemgr.cmx";
constexpr char kBasemgrHubPath[] = "/hub/c/basemgr.cmx/*/out/debug/basemgr";
constexpr char kShutdownBasemgrCommandString[] = "shutdown";

// Returns false if no basemgr debug service can be found, because
// basemgr is not running.
bool FindBasemgrDebugService(std::string* service_path) {
  glob_t globbuf;
  glob(kBasemgrHubPath, 0, nullptr, &globbuf);
  bool found = false;
  if (globbuf.gl_pathc > 0) {
    *service_path = globbuf.gl_pathv[0];
    found = true;
  }
  globfree(&globbuf);
  return found;
}

zx_status_t ShutdownBasemgr(async::Loop* loop) {
  // Get a connection to basemgr in order to shut it down.
  std::string service_path;
  if (!FindBasemgrDebugService(&service_path)) {
    // basemgr is not running.
    std::cerr << "basemgr does not appear to be running.";
    return ZX_OK;
  }
  fuchsia::modular::internal::BasemgrDebugPtr basemgr_debug;
  auto request = basemgr_debug.NewRequest().TakeChannel();
  auto service_connect_result = fdio_service_connect(service_path.c_str(), request.get());
  if (service_connect_result != ZX_OK) {
    std::cerr << "Could not connect to basemgr service at " << service_path << ": "
              << zx_status_get_string(service_connect_result);
    return service_connect_result;
  }

  basemgr_debug->Shutdown();
  // Wait for basemgr to shutdown.
  zx_status_t channel_close_status;
  basemgr_debug.set_error_handler([&channel_close_status, loop](zx_status_t status) {
    channel_close_status = status;
    loop->Quit();
  });
  loop->Run();
  loop->ResetQuit();
  if (channel_close_status != ZX_OK) {
    std::cerr << "basemgr did not tear down cleanly. Expected ZX_OK, got "
              << zx_status_get_string(channel_close_status);
  }
  return ZX_OK;
}

std::unique_ptr<vfs::PseudoDir> CreateConfigPseudoDir(std::string config_str) {
  auto dir = std::make_unique<vfs::PseudoDir>();
  dir->AddEntry(modular_config::kStartupConfigFilePath,
                std::make_unique<vfs::PseudoFile>(
                    config_str.length(), [config_str = std::move(config_str)](
                                             std::vector<uint8_t>* out, size_t /*unused*/) {
                      std::copy(config_str.begin(), config_str.end(), std::back_inserter(*out));
                      return ZX_OK;
                    }));
  return dir;
}

std::string GetUsage() {
  return R"(Control the lifecycle of instances of basemgr.

Usage: basemgr_launcher [<command>]

  <command>
    (none)    Launches a new instance of basemgr with a modular JSON configuration
              read from stdin.
    shutdown  Terminates the running instance of basemgr, if found.

Exmaples (from host machine):

  $ cat myconfig.json | fx shell basemgr_launcher
  $ fx shell basemgr_launcher shutdown
)";
}

std::string GetDefaultConfig() {
  auto config_reader = modular::ModularConfigReader(/*config=*/"{}");
  fuchsia::modular::session::BasemgrConfig basemgr_config = config_reader.GetBasemgrConfig();
  fuchsia::modular::session::SessionmgrConfig sessionmgr_config =
      config_reader.GetSessionmgrConfig();
  return modular::ModularConfigReader::GetConfigAsString(&basemgr_config, &sessionmgr_config);
}

int main(int argc, const char** argv) {
  syslog::SetTags({"basemgr_launcher"});
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);

  std::string config_str = "";
  if (argc > 1) {
    const auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
    const auto& positional_args = command_line.positional_args();
    const auto& cmd = positional_args.empty() ? "" : positional_args[0];

    if (cmd.empty()) {
      config_str = GetDefaultConfig();
    } else if (cmd == kShutdownBasemgrCommandString) {
      return ShutdownBasemgr(&loop);
    } else {
      std::cerr << GetUsage() << std::endl;
      return ZX_ERR_INVALID_ARGS;
    }
  } else {
    // Read the configuration file in from stdin.
    std::string line;
    while (getline(std::cin, line)) {
      config_str += line;
    }
  }

  // If basemgr is already running, shut it down first.
  if (files::Glob(kBasemgrHubPath).size() != 0) {
    auto result = ShutdownBasemgr(&loop);
    if (result != ZX_OK) {
      std::cerr << "Could not shut down running instance of basemgr: "
                << zx_status_get_string(result);
      return result;
    }
  }

  // Create the pseudo directory with our config "file" mapped to
  // kConfigFilename.
  auto config_dir = CreateConfigPseudoDir(config_str);
  fidl::InterfaceHandle<fuchsia::io::Directory> dir_handle;
  config_dir->Serve(fuchsia::io::OPEN_RIGHT_READABLE, dir_handle.NewRequest().TakeChannel());

  // Build a LaunchInfo with the config directory above mapped to
  // /config_override/data.
  fuchsia::sys::LaunchInfo launch_info;
  launch_info.url = kBasemgrUrl;
  launch_info.flat_namespace = fuchsia::sys::FlatNamespace::New();
  launch_info.flat_namespace->paths.push_back(modular_config::kOverriddenConfigDir);
  launch_info.flat_namespace->directories.push_back(dir_handle.TakeChannel());

  // Quit the loop when basemgr's out directory has been mounted.
  fuchsia::sys::ComponentControllerPtr controller;
  controller.events().OnDirectoryReady = [&controller, &loop] {
    controller->Detach();
    loop.Quit();
  };

  // Launch a basemgr instance with the custom namespace we created above.
  std::unique_ptr<sys::ComponentContext> context =
      sys::ComponentContext::CreateAndServeOutgoingDirectory();
  fuchsia::sys::LauncherPtr launcher;
  context->svc()->Connect(launcher.NewRequest());
  launcher->CreateComponent(std::move(launch_info), controller.NewRequest());

  loop.Run();
  return ZX_OK;
}
