// 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 <lib/modular/testing/cpp/test_harness_builder.h>

#include <sstream>

namespace modular {
namespace testing {
namespace {

std::string StringsToCSV(std::vector<std::string> strings) {
  std::stringstream csv;
  for (size_t i = 0; i < strings.size(); i++) {
    if (i != 0) {
      csv << ",";
    }
    csv << "\"" << strings[i] << "\"";
  }
  return csv.str();
}

std::string BuildExtraCmx(TestHarnessBuilder::InterceptOptions options) {
  std::stringstream ss;
  ss << R"({
    "sandbox": {
      "services": [
        )";
  ss << StringsToCSV(options.sandbox_services);
  ss << R"(
      ]
    }
  })";
  return ss.str();
}

bool BufferFromString(std::string str, fuchsia::mem::Buffer* buffer) {
  ZX_ASSERT(buffer != nullptr);
  uint64_t num_bytes = str.size();
  zx::vmo vmo;
  zx_status_t status = zx::vmo::create(num_bytes, 0u, &vmo);
  if (status < 0) {
    return false;
  }

  if (num_bytes > 0) {
    status = vmo.write(str.data(), 0, num_bytes);
    if (status < 0) {
      return false;
    }
  }

  buffer->vmo = std::move(vmo);
  buffer->size = num_bytes;
  return true;
}

}  // namespace

TestHarnessBuilder::TestHarnessBuilder(
    fuchsia::modular::testing::TestHarnessSpec spec)
    : spec_(std::move(spec)), env_services_(new vfs::PseudoDir) {}

TestHarnessBuilder::TestHarnessBuilder()
    : TestHarnessBuilder(fuchsia::modular::testing::TestHarnessSpec()) {}

fuchsia::modular::testing::TestHarnessSpec TestHarnessBuilder::BuildSpec() {
  fuchsia::io::DirectoryPtr dir;
  // This directory must be READABLE *and* WRITABLE, otherwise service
  // connections fail.
  env_services_->Serve(
      fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE,
      dir.NewRequest().TakeChannel());
  spec_.mutable_env_services()->set_service_dir(dir.Unbind().TakeChannel());
  return std::move(spec_);
}

TestHarnessBuilder::OnNewComponentHandler
TestHarnessBuilder::BuildOnNewComponentHandler() {
  return
      [handlers = std::move(handlers_)](
          fuchsia::sys::StartupInfo startup_info,
          fidl::InterfaceHandle<fuchsia::modular::testing::InterceptedComponent>
              component) {
        auto it = handlers.find(startup_info.launch_info.url);
        if (it == handlers.end()) {
          ZX_ASSERT_MSG(false, "Unexpected component URL: %s",
                        startup_info.launch_info.url.c_str());
        }

        it->second(std::move(startup_info), component.Bind());
      };
}

void TestHarnessBuilder::BuildAndRun(
    const fuchsia::modular::testing::TestHarnessPtr& test_harness) {
  test_harness.events().OnNewComponent = BuildOnNewComponentHandler();
  test_harness->Run(BuildSpec());
}

TestHarnessBuilder& TestHarnessBuilder::InterceptComponent(
    OnNewComponentHandler on_new_component, InterceptOptions options) {
  ZX_ASSERT(on_new_component);
  if (options.url.empty()) {
    options.url = modular::testing::GenerateFakeUrl();
  }

  fuchsia::modular::testing::InterceptSpec intercept_spec;
  intercept_spec.set_component_url(options.url);
  auto extra_cmx_contents = BuildExtraCmx(options);
  if (!extra_cmx_contents.empty()) {
    ZX_ASSERT(BufferFromString(extra_cmx_contents,
                               intercept_spec.mutable_extra_cmx_contents()));
  }
  spec_.mutable_components_to_intercept()->push_back(std::move(intercept_spec));

  handlers_.insert(std::make_pair(options.url, std::move(on_new_component)));
  return *this;
}

TestHarnessBuilder& TestHarnessBuilder::InterceptBaseShell(
    OnNewComponentHandler on_new_component, InterceptOptions options) {
  if (options.url.empty()) {
    options.url = modular::testing::GenerateFakeUrl("base_shell");
  }
  auto url = options.url;
  InterceptComponent(std::move(on_new_component), std::move(options));

  spec_.mutable_basemgr_config()
      ->mutable_base_shell()
      ->mutable_app_config()
      ->set_url(url);
  return *this;
}

TestHarnessBuilder& TestHarnessBuilder::InterceptSessionShell(
    OnNewComponentHandler on_new_component, InterceptOptions options) {
  if (options.url.empty()) {
    options.url = modular::testing::GenerateFakeUrl("session_shell");
  }
  auto url = options.url;
  InterceptComponent(std::move(on_new_component), std::move(options));

  fuchsia::modular::session::SessionShellMapEntry entry;
  entry.mutable_config()->mutable_app_config()->set_url(url);
  spec_.mutable_basemgr_config()->mutable_session_shell_map()->push_back(
      std::move(entry));
  return *this;
}

TestHarnessBuilder& TestHarnessBuilder::InterceptStoryShell(
    OnNewComponentHandler on_new_component, InterceptOptions options) {
  if (options.url.empty()) {
    options.url = modular::testing::GenerateFakeUrl("story_shell");
  }
  auto url = options.url;
  InterceptComponent(std::move(on_new_component), std::move(options));

  spec_.mutable_basemgr_config()
      ->mutable_story_shell()
      ->mutable_app_config()
      ->set_url(url);
  return *this;
}

TestHarnessBuilder& TestHarnessBuilder::AddService(
    const std::string& service_name, vfs::Service::Connector connector) {
  env_services_->AddEntry(service_name,
                          std::make_unique<vfs::Service>(std::move(connector)));
  return *this;
}

TestHarnessBuilder& TestHarnessBuilder::AddServiceFromComponent(
    const std::string& service_name, const std::string& component_url) {
  fuchsia::modular::testing::ComponentService svc;
  svc.name = service_name;
  svc.url = component_url;
  spec_.mutable_env_services()->mutable_services_from_components()->push_back(
      std::move(svc));
  return *this;
}

TestHarnessBuilder& TestHarnessBuilder::AddServiceFromServiceDirectory(
    const std::string& service_name,
    std::shared_ptr<sys::ServiceDirectory> services) {
  return AddService(service_name, [service_name, services](
                                      zx::channel request,
                                      async_dispatcher_t* dispatcher) mutable {
    services->Connect(service_name, std::move(request));
  });
}

std::string GenerateFakeUrl(std::string name) {
  name.erase(
      std::remove_if(name.begin(), name.end(),
                     [](auto const& c) -> bool { return !std::isalnum(c); }),
      name.end());

  uint32_t random_number = 0;
  zx_cprng_draw(&random_number, sizeof random_number);
  std::string rand_str = std::to_string(random_number);

  // Since we cannot depend on utlitites outside of the stdlib and SDK, here
  // is a quick way to format a string safely.
  std::string url;
  url = "fuchsia-pkg://example.com/GENERATED_URL_";
  url += rand_str;
  url += "#meta/GENERATED_URL_";
  if (!name.empty()) {
    url += name;
    url += "_";
  }
  url += rand_str;
  url += ".cmx";

  return url;
}

}  // namespace testing
}  // namespace modular
