// 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 <fuchsia/netstack/cpp/fidl.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/strings/string_printf.h>

#include "garnet/bin/guest/integration/enclosed_guest.h"

static constexpr char kGuestManagerUrl[] =
    "fuchsia-pkg://fuchsia.com/guest_manager#meta/guest_manager.cmx";
static constexpr char kRealm[] = "realmguestintegrationtest";
// TODO(MAC-229): Use consistent naming for the test utils here.
static constexpr char kFuchsiaTestUtilsUrl[] =
    "fuchsia-pkg://fuchsia.com/guest_integration_tests_utils";
static constexpr char kLinuxTestUtilDir[] = "/test_utils";
static constexpr zx::duration kLoopTimeout = zx::sec(5);
static constexpr zx::duration kLoopConditionStep = zx::msec(10);
static constexpr size_t kNumRetries = 40;
static constexpr zx::duration kRetryStep = zx::msec(200);

static bool RunLoopUntil(async::Loop* loop, fit::function<bool()> condition) {
  const zx::time deadline = zx::deadline_after(kLoopTimeout);
  while (zx::clock::get_monotonic() < deadline) {
    if (condition()) {
      return true;
    }
    loop->Run(zx::deadline_after(kLoopConditionStep));
    loop->ResetQuit();
  }
  return condition();
}

zx_status_t EnclosedGuest::Start() {
  real_services_->ConnectToService(real_env_.NewRequest());
  auto services = component::testing::EnvironmentServices::Create(
      real_env_, loop_.dispatcher());

  fuchsia::sys::LaunchInfo launch_info;
  launch_info.url = kGuestManagerUrl;
  zx_status_t status = services->AddServiceWithLaunchInfo(
      std::move(launch_info), fuchsia::guest::EnvironmentManager::Name_);
  if (status != ZX_OK) {
    return status;
  }

  status = services->AddService(mock_netstack_.GetHandler(),
                                fuchsia::netstack::Netstack::Name_);

  enclosing_environment_ = component::testing::EnclosingEnvironment::Create(
      kRealm, real_env_, std::move(services));
  bool environment_running = RunLoopUntil(
      &loop_, [this] { return enclosing_environment_->is_running(); });
  if (!environment_running) {
    return ZX_ERR_BAD_STATE;
  }

  fuchsia::guest::LaunchInfo guest_launch_info;
  status = LaunchInfo(&guest_launch_info);
  if (status != ZX_OK) {
    return status;
  }

  enclosing_environment_->ConnectToService(environment_manager_.NewRequest());
  environment_manager_->Create(guest_launch_info.url,
                               environment_controller_.NewRequest());

  environment_controller_->LaunchInstance(std::move(guest_launch_info),
                                          instance_controller_.NewRequest(),
                                          [this](uint32_t cid) {
                                            guest_cid_ = cid;
                                            loop_.Quit();
                                          });
  loop_.Run();

  zx::socket socket;
  instance_controller_->GetSerial(
      [&socket](zx::socket s) { socket = std::move(s); });
  bool socket_valid = RunLoopUntil(&loop_, [&] { return socket.is_valid(); });
  if (!socket_valid) {
    return ZX_ERR_BAD_STATE;
  }
  status = serial_.Start(std::move(socket));
  if (status != ZX_OK) {
    return status;
  }

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

  ready_ = true;
  return ZX_OK;
}

zx_status_t ZirconEnclosedGuest::LaunchInfo(
    fuchsia::guest::LaunchInfo* launch_info) {
  launch_info->url = kZirconGuestUrl;
  launch_info->args.push_back("--virtio-gpu=false");
  launch_info->args.push_back("--cmdline-add=kernel.serial=none");
  return ZX_OK;
}

zx_status_t ZirconEnclosedGuest::WaitForSystemReady() {
  for (size_t i = 0; i != kNumRetries; ++i) {
    std::string ps;
    zx_status_t status = Execute("ps", &ps);
    if (status != ZX_OK) {
      continue;
    }
    auto appmgr = ps.find("appmgr");
    if (appmgr == std::string::npos) {
      zx::nanosleep(zx::deadline_after(kRetryStep));
      continue;
    }
    return ZX_OK;
  }
  FXL_LOG(ERROR) << "Failed to wait for appmgr";
  return ZX_ERR_TIMED_OUT;
}

zx_status_t ZirconEnclosedGuest::RunUtil(const std::string& util,
                                         const std::string& args,
                                         std::string* result) {
  std::string cmd =
      fxl::StringPrintf("/bin/run %s#meta/%s.cmx %s", kFuchsiaTestUtilsUrl,
                        util.c_str(), args.c_str());
  return Execute(cmd, result);
}

zx_status_t LinuxEnclosedGuest::LaunchInfo(
    fuchsia::guest::LaunchInfo* launch_info) {
  launch_info->url = kLinuxGuestUrl;
  launch_info->args.push_back("--virtio-gpu=false");
  launch_info->args.push_back(
      "--cmdline=loglevel=0 console=hvc0 root=/dev/vda rw");
  return ZX_OK;
}

zx_status_t LinuxEnclosedGuest::WaitForSystemReady() {
  for (size_t i = 0; i != kNumRetries; ++i) {
    std::string response;
    zx_status_t status = Execute("echo guest ready", &response);
    if (status != ZX_OK) {
      continue;
    }
    auto ready = response.find("guest ready");
    if (ready == std::string::npos) {
      zx::nanosleep(zx::deadline_after(kRetryStep));
      continue;
    }
    return ZX_OK;
  }
  FXL_LOG(ERROR) << "Failed to wait for shell";
  return ZX_ERR_TIMED_OUT;
}

zx_status_t LinuxEnclosedGuest::RunUtil(const std::string& util,
                                        const std::string& args,
                                        std::string* result) {
  std::string cmd = fxl::StringPrintf("%s/%s %s", kLinuxTestUtilDir,
                                      util.c_str(), args.c_str());
  return Execute(cmd, result);
}