// 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_testing {
namespace {

std::string StringsToCSV(const 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(const 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::LaunchHandler 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(InterceptOptions options) {
  ZX_ASSERT(options.launch_handler);
  ZX_ASSERT(!options.url.empty());

  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(options.launch_handler)));
  return *this;
}

TestHarnessBuilder& TestHarnessBuilder::InterceptBaseShell(InterceptOptions options) {
  spec_.mutable_basemgr_config()->mutable_base_shell()->mutable_app_config()->set_url(options.url);
  InterceptComponent(std::move(options));
  return *this;
}

TestHarnessBuilder& TestHarnessBuilder::InterceptBaseShell(LaunchHandler handler,
                                                           InterceptOptions options) {
  options.launch_handler = std::move(handler);
  return InterceptBaseShell(std::move(options));
}

TestHarnessBuilder& TestHarnessBuilder::InterceptSessionShell(InterceptOptions options) {
  fuchsia::modular::session::SessionShellMapEntry entry;
  entry.mutable_config()->mutable_app_config()->set_url(options.url);
  spec_.mutable_basemgr_config()->mutable_session_shell_map()->push_back(std::move(entry));
  InterceptComponent(std::move(options));
  return *this;
}

TestHarnessBuilder& TestHarnessBuilder::InterceptStoryShell(InterceptOptions options) {
  spec_.mutable_basemgr_config()->mutable_story_shell()->mutable_app_config()->set_url(options.url);
  InterceptComponent(std::move(options));
  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));
  });
}

// static
std::string TestHarnessBuilder::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 modular_testing
